Skip to content

[Experimental] Generic Commitment Transaction Output - WIP DLC support #619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
3 changes: 3 additions & 0 deletions lightning-net-tokio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ mod tests {
fn handle_update_fulfill_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFulfillHTLC) {}
fn handle_update_fail_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFailHTLC) {}
fn handle_update_fail_malformed_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFailMalformedHTLC) {}
fn handle_update_add_dlc(&self, _their_node_id: &PublicKey, _msg: &UpdateAddDLC) {}
fn handle_update_countersign_dlc(&self, _their_node_id: &PublicKey, _msg: &UpdateCounterSignDLC) {}
fn handle_update_fulfill_dlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFulfillDLC) {}
fn handle_commitment_signed(&self, _their_node_id: &PublicKey, _msg: &CommitmentSigned) {}
fn handle_revoke_and_ack(&self, _their_node_id: &PublicKey, _msg: &RevokeAndACK) {}
fn handle_update_fee(&self, _their_node_id: &PublicKey, _msg: &UpdateFee) {}
Expand Down
486 changes: 304 additions & 182 deletions lightning/src/ln/channel.rs

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ pub(super) enum HTLCFailureMsg {
pub(super) enum PendingHTLCStatus {
Forward(PendingHTLCInfo),
Fail(HTLCFailureMsg),
Dummy, //non-routed payload (aka DLC)
}

pub(super) enum HTLCForwardInfo {
Expand Down Expand Up @@ -1283,6 +1284,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
update_fulfill_htlcs: Vec::new(),
update_fail_htlcs: Vec::new(),
update_fail_malformed_htlcs: Vec::new(),
update_add_dlcs: Vec::new(),
update_countersign_dlcs: Vec::new(),
update_fee: None,
commitment_signed,
},
Expand Down Expand Up @@ -1673,6 +1676,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
update_fulfill_htlcs: Vec::new(),
update_fail_htlcs: fail_htlc_msgs,
update_fail_malformed_htlcs: Vec::new(),
update_add_dlcs: Vec::new(),
update_countersign_dlcs: Vec::new(),
update_fee: None,
commitment_signed: commitment_msg,
},
Expand Down Expand Up @@ -2050,6 +2055,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
update_fulfill_htlcs: vec![msg],
update_fail_htlcs: Vec::new(),
update_fail_malformed_htlcs: Vec::new(),
update_add_dlcs: Vec::new(),
update_countersign_dlcs: Vec::new(),
update_fee: None,
commitment_signed,
}
Expand Down Expand Up @@ -2571,6 +2578,29 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
}
}

fn internal_update_add_dlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateAddDLC) -> Result<(), MsgHandleErrInternal> {
let mut channel_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_lock;
match channel_state.by_id.entry(msg.channel_id) {
hash_map::Entry::Occupied(mut chan) => {
if chan.get().get_their_node_id() != *their_node_id {
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
}
try_chan_entry!(self, chan.get_mut().update_add_dlc(&msg, PendingHTLCStatus::Dummy), channel_state, chan);
},
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
}
Ok(())
}

fn internal_update_countersign_dlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateCounterSignDLC) -> Result<(), MsgHandleErrInternal> {
Ok(())
}

fn internal_update_fulfill_dlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFulfillDLC) -> Result<(), MsgHandleErrInternal> {
Ok(())
}

fn internal_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(), MsgHandleErrInternal> {
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_state_lock;
Expand Down Expand Up @@ -2606,6 +2636,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
update_fulfill_htlcs: Vec::new(),
update_fail_htlcs: Vec::new(),
update_fail_malformed_htlcs: Vec::new(),
update_add_dlcs: Vec::new(),
update_countersign_dlcs: Vec::new(),
update_fee: None,
commitment_signed: msg,
},
Expand Down Expand Up @@ -2869,6 +2901,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
update_fulfill_htlcs: Vec::new(),
update_fail_htlcs: Vec::new(),
update_fail_malformed_htlcs: Vec::new(),
update_add_dlcs: Vec::new(),
update_countersign_dlcs: Vec::new(),
update_fee: Some(update_fee),
commitment_signed,
},
Expand Down Expand Up @@ -3175,6 +3209,21 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
let _ = handle_error!(self, self.internal_update_fail_malformed_htlc(their_node_id, msg), *their_node_id);
}

fn handle_update_add_dlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateAddDLC) {
let _ = self.total_consistency_lock.read().unwrap();
let _ = handle_error!(self, self.internal_update_add_dlc(their_node_id, msg), *their_node_id);
}

fn handle_update_countersign_dlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateCounterSignDLC) {
let _ = self.total_consistency_lock.read().unwrap();
let _ = handle_error!(self, self.internal_update_countersign_dlc(their_node_id, msg), *their_node_id);
}

fn handle_update_fulfill_dlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFulfillDLC) {
let _ = self.total_consistency_lock.read().unwrap();
let _ = handle_error!(self, self.internal_update_fulfill_dlc(their_node_id, msg), *their_node_id);
}

fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) {
let _ = self.total_consistency_lock.read().unwrap();
let _ = handle_error!(self, self.internal_commitment_signed(their_node_id, msg), *their_node_id);
Expand Down Expand Up @@ -3426,6 +3475,9 @@ impl Writeable for PendingHTLCStatus {
1u8.write(writer)?;
fail_msg.write(writer)?;
}
&PendingHTLCStatus::Dummy => {
2u8.write(writer)?;
}
}
Ok(())
}
Expand All @@ -3436,6 +3488,7 @@ impl Readable for PendingHTLCStatus {
match <u8 as Readable>::read(reader)? {
0 => Ok(PendingHTLCStatus::Forward(Readable::read(reader)?)),
1 => Ok(PendingHTLCStatus::Fail(Readable::read(reader)?)),
2 => Ok(PendingHTLCStatus::Dummy),
_ => Err(DecodeError::InvalidValue),
}
}
Expand Down
56 changes: 56 additions & 0 deletions lightning/src/ln/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7685,3 +7685,59 @@ fn test_update_err_monitor_lockdown() {
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
}

#[test]
fn test_send_dlc() {
// Create a channel and send a basic DLC through the following flow
//
// update_add_dlc
// ------------------------------->
//
// update_countersign_dlc
// <-------------------------------
//
// commitment_signed (+cet_sigs)
// ------------------------------->
//
// update_countersign_dlc
// ------------------------------->
//
// revoke_and_ack
// <-------------------------------
//
// commitment_signed (+cet_sigs)
// <-------------------------------
//
// revoke_and_ack
// ------------------------------->
//
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None, None]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::nown());
// Create a dlc payload on Alice
let dlc_offer = make_dummy_dlc();
let mut dlc_event = nodes[0].node.send_dlc(dlc_offer).unwrap();

// Bob receives dlc payload
nodes[1].node.handle_update_add_dlc(&nodes[1].node.get_our_node_id(), &dlc_event.msgs[0]);
let mut bob_events = nodes[1].node.get_and_clear_pending_msg_events();

// Alice receives dlc counter-sig and sends back commitment_signed + counter_sig
nodes[0].node.handle_update_countersign_dlc(&nodes[1].node.get_our_node_id(), &bob_event.msgs[0]);
//XXX fetch oracle ?

nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &alice_events.msg[0]);
nodes[1].node.handle_update_countersign_dlc(&nodes[0].node.get_our_node_id(), &alice_events.msgs[0]);

// Bob sends back revoke_and_ack+commitment_signed
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bob_revoke_and_ack);
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bob_cs);

// Alice sends back her revoke_and_ack
nodes[1].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &alice_revoke_and_ack);


//XXX add events fetching accordingly
}
58 changes: 58 additions & 0 deletions lightning/src/ln/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,33 @@ pub struct UpdateFailMalformedHTLC {
pub(crate) failure_code: u16,
}

/// An update_add_dlc message to be sent or received from a peer
#[derive(Clone, PartialEq)]
pub struct UpdateAddDLC {
pub(crate) channel_id: [u8; 32],
pub(crate) event_id: u64,
pub(crate) amount_msat: u64,
pub(crate) payment_hash: PaymentHash,
pub(crate) maturity: u32,
pub(crate) cet_sigs: Vec<Signature>,
}

/// An update_countersign_dlc message to be sent or received from a peer
#[derive(Clone, PartialEq)]
pub struct UpdateCounterSignDLC {
pub(crate) channel_id: [u8; 32],
pub(crate) event_id: u64,
pub(crate) cet_sigs: Vec<Signature>
}

/// An update_fulfill_dlc message to be sent or received from a peer
#[derive(Clone, PartialEq)]
pub struct UpdateFulfillDLC {
pub(crate) channel_id: [u8; 32],
pub(crate) event_id: u64,
pub(crate) oracle_sig: u64,
}

/// A commitment_signed message to be sent or received from a peer
#[derive(Clone, PartialEq)]
pub struct CommitmentSigned {
Expand Down Expand Up @@ -479,6 +506,10 @@ pub struct CommitmentUpdate {
pub update_fail_htlcs: Vec<UpdateFailHTLC>,
/// update_fail_malformed_htlc messages which should be sent
pub update_fail_malformed_htlcs: Vec<UpdateFailMalformedHTLC>,
/// update_add_dlc messages which should be sent
pub update_add_dlcs: Vec<UpdateAddDLC>,
/// update_countersign_dlc messages which should be sent
pub update_countersign_dlcs: Vec<UpdateCounterSignDLC>,
/// An update_fee message which should be sent
pub update_fee: Option<UpdateFee>,
/// Finally, the commitment_signed message which should be sent
Expand Down Expand Up @@ -558,6 +589,12 @@ pub trait ChannelMessageHandler : events::MessageSendEventsProvider + Send + Syn
fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC);
/// Handle an incoming update_fail_malformed_htlc message from the given peer.
fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailMalformedHTLC);
/// Handle an incoming update_add_dlc message from the given peer.
fn handle_update_add_dlc(&self, their_node_id: &PublicKey, msg: &UpdateAddDLC);
/// Handle an incoming update_countersign_dlc message from the given peer.
fn handle_update_countersign_dlc(&self, their_node_id: &PublicKey, msg: &UpdateCounterSignDLC);
/// Handle an incoming update_fulfill_dlc message from the given peer.
fn handle_update_fulfill_dlc(&self, their_node_id: &PublicKey, msg: &UpdateFulfillDLC);
/// Handle an incoming commitment_signed message from the given peer.
fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &CommitmentSigned);
/// Handle an incoming revoke_and_ack message from the given peer.
Expand Down Expand Up @@ -931,6 +968,27 @@ impl_writeable!(UpdateFulfillHTLC, 32+8+32, {
payment_preimage
});

impl_writeable!(UpdateAddDLC, 32+8+288, {
channel_id,
event_id,
amount_msat,
payment_hash,
maturity,
cet_sigs
});

impl_writeable!(UpdateCounterSignDLC, 32+8+72, {
channel_id,
event_id,
cet_sigs
});

impl_writeable!(UpdateFulfillDLC, 32+8+72, {
channel_id,
event_id,
oracle_sig
});

impl_writeable_len_match!(OnionErrorPacket, {
{ OnionErrorPacket { ref data, .. }, 2 + data.len() }
}, {
Expand Down
12 changes: 10 additions & 2 deletions lightning/src/ln/peer_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,15 @@ impl<Descriptor: SocketDescriptor, CM: Deref> PeerManager<Descriptor, CM> where
// TODO: forward msg along to all our other peers!
}
},

wire::Message::UpdateAddDLC(msg) => {
self.message_handler.chan_handler.handle_update_add_dlc(&peer.their_node_id.unwrap(), &msg);
},
wire::Message::UpdateCounterSignDLC(msg) => {
self.message_handler.chan_handler.handle_update_countersign_dlc(&peer.their_node_id.unwrap(), &msg);
},
wire::Message::UpdateFulfillDLC(msg) => {
self.message_handler.chan_handler.handle_update_fulfill_dlc(&peer.their_node_id.unwrap(), &msg);
},
// Unknown messages:
wire::Message::Unknown(msg_type) if msg_type.is_even() => {
log_debug!(self, "Received unknown even message of type {}, disconnecting peer!", msg_type);
Expand Down Expand Up @@ -896,7 +904,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref> PeerManager<Descriptor, CM> where
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg)));
self.do_attempt_write_data(&mut descriptor, peer);
},
MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed, ref update_add_dlcs, ref update_countersign_dlcs } } => {
log_trace!(self, "Handling UpdateHTLCs event in peer_handler for node {} with {} adds, {} fulfills, {} fails for channel {}",
log_pubkey!(node_id),
update_add_htlcs.len(),
Expand Down
27 changes: 27 additions & 0 deletions lightning/src/ln/wire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ pub enum Message {
UpdateFulfillHTLC(msgs::UpdateFulfillHTLC),
UpdateFailHTLC(msgs::UpdateFailHTLC),
UpdateFailMalformedHTLC(msgs::UpdateFailMalformedHTLC),
UpdateAddDLC(msgs::UpdateAddDLC),
UpdateCounterSignDLC(msgs::UpdateCounterSignDLC),
UpdateFulfillDLC(msgs::UpdateFulfillDLC),
CommitmentSigned(msgs::CommitmentSigned),
RevokeAndACK(msgs::RevokeAndACK),
UpdateFee(msgs::UpdateFee),
Expand Down Expand Up @@ -73,6 +76,9 @@ impl Message {
&Message::UpdateFulfillHTLC(ref msg) => msg.type_id(),
&Message::UpdateFailHTLC(ref msg) => msg.type_id(),
&Message::UpdateFailMalformedHTLC(ref msg) => msg.type_id(),
&Message::UpdateAddDLC(ref msg) => msg.type_id(),
&Message::UpdateCounterSignDLC(ref msg) => msg.type_id(),
&Message::UpdateFulfillDLC(ref msg) => msg.type_id(),
&Message::CommitmentSigned(ref msg) => msg.type_id(),
&Message::RevokeAndACK(ref msg) => msg.type_id(),
&Message::UpdateFee(ref msg) => msg.type_id(),
Expand Down Expand Up @@ -153,6 +159,15 @@ pub fn read<R: ::std::io::Read>(buffer: &mut R) -> Result<Message, msgs::DecodeE
msgs::UpdateFailMalformedHTLC::TYPE => {
Ok(Message::UpdateFailMalformedHTLC(Readable::read(buffer)?))
},
msgs::UpdateAddDLC::TYPE => {
Ok(Message::UpdateAddDLC(Readable::read(buffer)?))
},
msgs::UpdateCounterSignDLC::TYPE => {
Ok(Message::UpdateCounterSignDLC(Readable::read(buffer)?))
},
msgs::UpdateFulfillDLC::TYPE => {
Ok(Message::UpdateFulfillDLC(Readable::read(buffer)?))
},
msgs::CommitmentSigned::TYPE => {
Ok(Message::CommitmentSigned(Readable::read(buffer)?))
},
Expand Down Expand Up @@ -271,6 +286,18 @@ impl Encode for msgs::UpdateFailMalformedHTLC {
const TYPE: u16 = 135;
}

impl Encode for msgs::UpdateAddDLC {
const TYPE: u16 = 0xeffe;
}

impl Encode for msgs::UpdateCounterSignDLC {
const TYPE: u16 = 0xfeef;
}

impl Encode for msgs::UpdateFulfillDLC {
const TYPE: u16 = 0xfefe;
}

impl Encode for msgs::CommitmentSigned {
const TYPE: u16 = 132;
}
Expand Down
3 changes: 3 additions & 0 deletions lightning/src/util/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler {
fn handle_update_fulfill_htlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFulfillHTLC) {}
fn handle_update_fail_htlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFailHTLC) {}
fn handle_update_fail_malformed_htlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFailMalformedHTLC) {}
fn handle_update_add_dlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateAddDLC) {}
fn handle_update_countersign_dlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateCounterSignDLC) {}
fn handle_update_fulfill_dlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFulfillDLC) {}
fn handle_commitment_signed(&self, _their_node_id: &PublicKey, _msg: &msgs::CommitmentSigned) {}
fn handle_revoke_and_ack(&self, _their_node_id: &PublicKey, _msg: &msgs::RevokeAndACK) {}
fn handle_update_fee(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFee) {}
Expand Down