Skip to content
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