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

Introduce custom TLV support for OnionMessage #2830

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ impl MessageRouter for FuzzRouter {
}

fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
&self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
_secp_ctx: &Secp256k1<T>,
&self, _recipient: PublicKey, _context: MessageContext, _custom_tlvs: Vec<u8>,
_peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedMessagePath>, ()> {
unreachable!()
}
Expand Down
4 changes: 2 additions & 2 deletions fuzz/src/full_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ impl MessageRouter for FuzzRouter {
}

fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
&self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
_secp_ctx: &Secp256k1<T>,
&self, _recipient: PublicKey, _context: MessageContext, _custom_tlvs: Vec<u8>,
_peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedMessagePath>, ()> {
unreachable!()
}
Expand Down
6 changes: 3 additions & 3 deletions fuzz/src/onion_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ impl MessageRouter for TestMessageRouter {
}

fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
&self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
_secp_ctx: &Secp256k1<T>,
&self, _recipient: PublicKey, _context: MessageContext, _custom_tlvs: Vec<u8>,
_peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedMessagePath>, ()> {
unreachable!()
}
Expand All @@ -112,7 +112,7 @@ struct TestOffersMessageHandler {}
impl OffersMessageHandler for TestOffersMessageHandler {
fn handle_message(
&self, _message: OffersMessage, _context: Option<OffersContext>,
_responder: Option<Responder>,
_custom_tlvs: Option<Vec<u8>>, _responder: Option<Responder>,
) -> Option<(OffersMessage, ResponseInstruction)> {
None
}
Expand Down
18 changes: 11 additions & 7 deletions lightning/src/blinded_path/message.rs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First commit message doesn't seem accurate. It says "reply path of a sent onion message", but this isn't restricted to reply paths. One could use this to include custom TLVs in an blinded path, including one in an offer.

Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ impl Readable for BlindedMessagePath {
impl BlindedMessagePath {
/// Create a one-hop blinded path for a message.
pub fn one_hop<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
recipient_node_id: PublicKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>
recipient_node_id: PublicKey, context: MessageContext, custom_tlvs: Vec<u8>, entropy_source: ES, secp_ctx: &Secp256k1<T>
) -> Result<Self, ()> where ES::Target: EntropySource {
Self::new(&[], recipient_node_id, context, entropy_source, secp_ctx)
Self::new(&[], recipient_node_id, context, custom_tlvs, entropy_source, secp_ctx)
}

/// Create a path for an onion message, to be forwarded along `node_pks`. The last node
Expand All @@ -67,7 +67,7 @@ impl BlindedMessagePath {
// TODO: make all payloads the same size with padding + add dummy hops
pub fn new<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey,
context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>,
context: MessageContext, custom_tlvs: Vec<u8>, entropy_source: ES, secp_ctx: &Secp256k1<T>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should pass ReceiveTlvs like we do for payment paths? Though that would allow not setting a MessageContext, which may be fine.

) -> Result<Self, ()> where ES::Target: EntropySource {
let introduction_node = IntroductionNode::NodeId(
intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id)
Expand All @@ -80,7 +80,7 @@ impl BlindedMessagePath {
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
blinded_hops: blinded_hops(
secp_ctx, intermediate_nodes, recipient_node_id,
context, &blinding_secret,
context, custom_tlvs, &blinding_secret,
).map_err(|_| ())?,
}))
}
Expand Down Expand Up @@ -241,7 +241,10 @@ pub(crate) struct ReceiveTlvs {
/// If `context` is `Some`, it is used to identify the blinded path that this onion message is
/// sending to. This is useful for receivers to check that said blinded path is being used in
/// the right context.
pub context: Option<MessageContext>
pub context: Option<MessageContext>,

/// Custom Tlvs. A user can use this to send custom tlvs information back to themself.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure someone reading this would understand what it means. Could you be clearer?

pub custom_tlvs: Option<Vec<u8>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this is just custom data rather than custom TLVs. Nothing is enforcing that this data is encoded as a TLV stream.

@TheBlueMatt Not sure if you have any thoughts on how if we should make this a Vec<(u64, Vec<u8>)> instead? And, if so, if we should encode it inside type 65539 or place them directly in ReceiveTlvs, restricting TLVs >= 2^16 and all the checks that that entails.

}

impl Writeable for ForwardTlvs {
Expand All @@ -265,6 +268,7 @@ impl Writeable for ReceiveTlvs {
// TODO: write padding
encode_tlv_stream!(writer, {
(65537, self.context, option),
(65539, self.custom_tlvs, option),
});
Ok(())
}
Expand Down Expand Up @@ -456,7 +460,7 @@ impl_writeable_tlv_based!(DNSResolverContext, {
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[MessageForwardNode],
recipient_node_id: PublicKey, context: MessageContext, session_priv: &SecretKey,
recipient_node_id: PublicKey, context: MessageContext, custom_tlvs: Vec<u8>, session_priv: &SecretKey,
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
let pks = intermediate_nodes.iter().map(|node| node.node_id)
.chain(core::iter::once(recipient_node_id));
Expand All @@ -468,7 +472,7 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
None => NextMessageHop::NodeId(pubkey),
})
.map(|next_hop| ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None }))
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs{ context: Some(context) })));
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs{ context: Some(context), custom_tlvs: Some(custom_tlvs) })));

let path = pks.zip(tlvs);

Expand Down
12 changes: 11 additions & 1 deletion lightning/src/blinded_path/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ pub struct ReceiveTlvs {
pub payment_constraints: PaymentConstraints,
/// Context for the receiver of this payment.
pub payment_context: PaymentContext,
/// Custom Tlvs
pub custom_tlvs: Vec<u8>,
}

/// Data to construct a [`BlindedHop`] for sending a payment over.
Expand Down Expand Up @@ -404,7 +406,8 @@ impl Writeable for ReceiveTlvs {
encode_tlv_stream!(w, {
(12, self.payment_constraints, required),
(65536, self.payment_secret, required),
(65537, self.payment_context, required)
(65537, self.payment_context, required),
(65539, self.custom_tlvs, (default_value, Vec::new())),
});
Ok(())
}
Expand Down Expand Up @@ -432,6 +435,7 @@ impl Readable for BlindedPaymentTlvs {
(14, features, (option, encoding: (BlindedHopFeatures, WithoutLength))),
(65536, payment_secret, option),
(65537, payment_context, (default_value, PaymentContext::unknown())),
(65539, custom_tlvs, (default_value, Vec::new()))
});
let _padding: Option<utils::Padding> = _padding;

Expand All @@ -452,6 +456,7 @@ impl Readable for BlindedPaymentTlvs {
payment_secret: payment_secret.ok_or(DecodeError::InvalidValue)?,
payment_constraints: payment_constraints.0.unwrap(),
payment_context: payment_context.0.unwrap(),
custom_tlvs: custom_tlvs.0.unwrap(),
}))
}
}
Expand Down Expand Up @@ -683,6 +688,7 @@ mod tests {
htlc_minimum_msat: 1,
},
payment_context: PaymentContext::unknown(),
custom_tlvs: Vec::new(),
};
let htlc_maximum_msat = 100_000;
let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat, 12).unwrap();
Expand All @@ -702,6 +708,7 @@ mod tests {
htlc_minimum_msat: 1,
},
payment_context: PaymentContext::unknown(),
custom_tlvs: Vec::new(),
};
let blinded_payinfo = super::compute_payinfo(&[], &recv_tlvs, 4242, TEST_FINAL_CLTV as u16).unwrap();
assert_eq!(blinded_payinfo.fee_base_msat, 0);
Expand Down Expand Up @@ -758,6 +765,7 @@ mod tests {
htlc_minimum_msat: 3,
},
payment_context: PaymentContext::unknown(),
custom_tlvs: Vec::new(),
};
let htlc_maximum_msat = 100_000;
let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat, TEST_FINAL_CLTV as u16).unwrap();
Expand Down Expand Up @@ -811,6 +819,7 @@ mod tests {
htlc_minimum_msat: 1,
},
payment_context: PaymentContext::unknown(),
custom_tlvs: Vec::new(),
};
let htlc_minimum_msat = 3798;
assert!(super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_minimum_msat - 1, TEST_FINAL_CLTV as u16).is_err());
Expand Down Expand Up @@ -868,6 +877,7 @@ mod tests {
htlc_minimum_msat: 1,
},
payment_context: PaymentContext::unknown(),
custom_tlvs: Vec::new()
};

let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, 10_000, TEST_FINAL_CLTV as u16).unwrap();
Expand Down
13 changes: 10 additions & 3 deletions lightning/src/ln/blinded_payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ fn blinded_payment_path(
intro_node_min_htlc_opt.unwrap_or_else(|| channel_upds.last().unwrap().htlc_minimum_msat),
},
payment_context: PaymentContext::unknown(),
custom_tlvs: Vec::new(),
};
let mut secp_ctx = Secp256k1::new();
BlindedPaymentPath::new(
Expand Down Expand Up @@ -120,6 +121,7 @@ fn do_one_hop_blinded_path(success: bool) {
htlc_minimum_msat: chan_upd.htlc_minimum_msat,
},
payment_context: PaymentContext::unknown(),
custom_tlvs: Vec::new(),
};
let mut secp_ctx = Secp256k1::new();
let blinded_path = BlindedPaymentPath::new(
Expand Down Expand Up @@ -164,6 +166,7 @@ fn mpp_to_one_hop_blinded_path() {
htlc_minimum_msat: chan_upd_1_3.htlc_minimum_msat,
},
payment_context: PaymentContext::unknown(),
custom_tlvs: Vec::new(),
};
let blinded_path = BlindedPaymentPath::new(
&[], nodes[3].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16,
Expand Down Expand Up @@ -1310,6 +1313,7 @@ fn custom_tlvs_to_blinded_path() {
htlc_minimum_msat: chan_upd.htlc_minimum_msat,
},
payment_context: PaymentContext::unknown(),
custom_tlvs: vec![43, 43]
};
let mut secp_ctx = Secp256k1::new();
let blinded_path = BlindedPaymentPath::new(
Expand All @@ -1323,7 +1327,8 @@ fn custom_tlvs_to_blinded_path() {
);

let recipient_onion_fields = RecipientOnionFields::spontaneous_empty()
.with_custom_tlvs(vec![((1 << 16) + 1, vec![42, 42])])
.with_user_custom_tlvs(vec![43, 43])
.with_sender_custom_tlvs(vec![((1 << 16) + 3, vec![42, 42])])
.unwrap();
nodes[0].node.send_payment(payment_hash, recipient_onion_fields.clone(),
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
Expand All @@ -1336,11 +1341,13 @@ fn custom_tlvs_to_blinded_path() {
let path = &[&nodes[1]];
let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, ev)
.with_payment_secret(payment_secret)
.with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone());
.with_user_custom_tlvs(recipient_onion_fields.user_custom_tlvs.clone())
.with_sender_custom_tlvs(recipient_onion_fields.sender_custom_tlvs.clone());
do_pass_along_path(args);
claim_payment_along_route(
ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
.with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone())
.with_user_custom_tlvs(recipient_onion_fields.user_custom_tlvs.clone())
.with_sender_custom_tlvs(recipient_onion_fields.sender_custom_tlvs.clone())
);
}

Expand Down
Loading
Loading