Skip to content
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
6 changes: 2 additions & 4 deletions lightning-dns-resolver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,7 @@ mod test {
context,
&keys,
secp_ctx,
)
.unwrap()])
)])
}
}
impl Deref for DirectlyConnectedRouter {
Expand Down Expand Up @@ -349,8 +348,7 @@ mod test {
query_context,
&*payer_keys,
&secp_ctx,
)
.unwrap();
);
payer.pending_messages.lock().unwrap().push((
DNSResolverMessage::DNSSECQuery(msg),
MessageSendInstructions::WithSpecifiedReplyPath {
Expand Down
17 changes: 15 additions & 2 deletions lightning-types/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#channel-quiescence) for more information).
//! - `ZeroFeeCommitments` - A channel type which always uses zero transaction fee on commitment transactions.
//! (see [BOLT PR #1228](https://github.com/lightning/bolts/pull/1228) for more info).
//! - `HtlcHold` - requires/supports holding HTLCs and forwarding on receipt of an onion message
//! (see [BOLT-2](https://github.com/lightning/bolts/pull/989/files) for more information).
//!
//! LDK knows about the following features, but does not support them:
//! - `AnchorsNonzeroFeeHtlcTx` - the initial version of anchor outputs, which was later found to be
Expand Down Expand Up @@ -161,7 +163,7 @@ mod sealed {
// Byte 5
ProvideStorage | ChannelType | SCIDPrivacy | AnchorZeroFeeCommitments,
// Byte 6
ZeroConf,
ZeroConf | HtlcHold,
// Byte 7
Trampoline | SimpleClose,
]
Expand All @@ -182,7 +184,7 @@ mod sealed {
// Byte 5
ProvideStorage | ChannelType | SCIDPrivacy | AnchorZeroFeeCommitments,
// Byte 6
ZeroConf | Keysend,
ZeroConf | HtlcHold | Keysend,
// Byte 7
Trampoline | SimpleClose,
// Byte 8 - 31
Expand Down Expand Up @@ -640,6 +642,17 @@ mod sealed {
define_feature!(51, ZeroConf, [InitContext, NodeContext, ChannelTypeContext],
"Feature flags for accepting channels with zero confirmations. Called `option_zeroconf` in the BOLTs",
set_zero_conf_optional, set_zero_conf_required, supports_zero_conf, requires_zero_conf);
define_feature!(
53,
HtlcHold,
[InitContext, NodeContext],
"Feature flags for holding HTLCs and forwarding on receipt of an onion message",
set_htlc_hold_optional,
set_htlc_hold_required,
clear_htlc_hold,
supports_htlc_hold,
requires_htlc_hold
);
define_feature!(
55,
Keysend,
Expand Down
39 changes: 24 additions & 15 deletions lightning/src/blinded_path/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::blinded_path::{BlindedHop, BlindedPath, Direction, IntroductionNode,
use crate::crypto::streams::ChaChaPolyReadAdapter;
use crate::io;
use crate::io::Cursor;
use crate::ln::channelmanager::PaymentId;
use crate::ln::channelmanager::{InterceptId, PaymentId};
use crate::ln::msgs::DecodeError;
use crate::ln::onion_utils;
use crate::offers::nonce::Nonce;
Expand Down Expand Up @@ -57,23 +57,19 @@ impl BlindedMessagePath {
pub fn one_hop<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
recipient_node_id: PublicKey, local_node_receive_key: ReceiveAuthKey,
context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>,
) -> Result<Self, ()>
) -> Self
where
ES::Target: EntropySource,
{
Self::new(&[], recipient_node_id, local_node_receive_key, context, entropy_source, secp_ctx)
}

/// Create a path for an onion message, to be forwarded along `node_pks`. The last node
/// pubkey in `node_pks` will be the destination node.
///
/// Errors if no hops are provided or if `node_pk`(s) are invalid.
// TODO: make all payloads the same size with padding + add dummy hops
/// Create a path for an onion message, to be forwarded along `node_pks`.
pub fn new<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey,
local_node_receive_key: ReceiveAuthKey, context: MessageContext, entropy_source: ES,
secp_ctx: &Secp256k1<T>,
) -> Result<Self, ()>
) -> Self
where
ES::Target: EntropySource,
{
Expand All @@ -96,7 +92,7 @@ impl BlindedMessagePath {
intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey,
dummy_hop_count: usize, local_node_receive_key: ReceiveAuthKey, context: MessageContext,
entropy_source: ES, secp_ctx: &Secp256k1<T>,
) -> Result<Self, ()>
) -> Self
where
ES::Target: EntropySource,
{
Expand All @@ -107,7 +103,7 @@ impl BlindedMessagePath {
let blinding_secret =
SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");

Ok(Self(BlindedPath {
Self(BlindedPath {
introduction_node,
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
blinded_hops: blinded_hops(
Expand All @@ -118,9 +114,8 @@ impl BlindedMessagePath {
context,
&blinding_secret,
local_node_receive_key,
)
.map_err(|_| ())?,
}))
),
})
}

/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
Expand Down Expand Up @@ -561,7 +556,7 @@ pub enum AsyncPaymentsContext {
},
/// Context contained within the reply [`BlindedMessagePath`] we put in outbound
/// [`HeldHtlcAvailable`] messages, provided back to us in corresponding [`ReleaseHeldHtlc`]
/// messages.
/// messages if we are an always-online sender paying an async recipient.
///
/// [`HeldHtlcAvailable`]: crate::onion_message::async_payments::HeldHtlcAvailable
/// [`ReleaseHeldHtlc`]: crate::onion_message::async_payments::ReleaseHeldHtlc
Expand All @@ -582,6 +577,17 @@ pub enum AsyncPaymentsContext {
/// able to trivially ask if we're online forever.
path_absolute_expiry: core::time::Duration,
},
/// Context contained within the reply [`BlindedMessagePath`] put in outbound
/// [`HeldHtlcAvailable`] messages, provided back to the async sender's always-online counterparty
/// in corresponding [`ReleaseHeldHtlc`] messages.
///
/// [`HeldHtlcAvailable`]: crate::onion_message::async_payments::HeldHtlcAvailable
/// [`ReleaseHeldHtlc`]: crate::onion_message::async_payments::ReleaseHeldHtlc
ReleaseHeldHtlc {
/// An identifier for the HTLC that should be released by us as the sender's always-online
/// channel counterparty to the often-offline recipient.
intercept_id: InterceptId,
},
}

impl_writeable_tlv_based_enum!(MessageContext,
Expand Down Expand Up @@ -637,6 +643,9 @@ impl_writeable_tlv_based_enum!(AsyncPaymentsContext,
(2, invoice_slot, required),
(4, path_absolute_expiry, required),
},
(6, ReleaseHeldHtlc) => {
(0, intercept_id, required),
},
);

/// Contains a simple nonce for use in a blinded path's context.
Expand Down Expand Up @@ -669,7 +678,7 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[MessageForwardNode],
recipient_node_id: PublicKey, dummy_hop_count: usize, context: MessageContext,
session_priv: &SecretKey, local_node_receive_key: ReceiveAuthKey,
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
) -> Vec<BlindedHop> {
let dummy_count = cmp::min(dummy_hop_count, MAX_DUMMY_HOPS_COUNT);
let pks = intermediate_nodes
.iter()
Expand Down
6 changes: 2 additions & 4 deletions lightning/src/blinded_path/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ impl BlindedPaymentPath {
/// Create a blinded path for a payment, to be forwarded along `intermediate_nodes`.
///
/// Errors if:
/// * a provided node id is invalid
/// * [`BlindedPayInfo`] calculation results in an integer overflow
/// * any unknown features are required in the provided [`ForwardTlvs`]
// TODO: make all payloads the same size with padding + add dummy hops
Expand Down Expand Up @@ -151,8 +150,7 @@ impl BlindedPaymentPath {
payee_node_id,
payee_tlvs,
&blinding_secret,
)
.map_err(|_| ())?,
),
},
payinfo: blinded_payinfo,
})
Expand Down Expand Up @@ -663,7 +661,7 @@ pub(crate) const PAYMENT_PADDING_ROUND_OFF: usize = 30;
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[PaymentForwardNode], payee_node_id: PublicKey,
payee_tlvs: ReceiveTlvs, session_priv: &SecretKey,
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
) -> Vec<BlindedHop> {
let pks = intermediate_nodes
.iter()
.map(|node| (node.node_id, None))
Expand Down
32 changes: 13 additions & 19 deletions lightning/src/blinded_path/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,8 @@ macro_rules! build_keys_helper {
hmac.input(encrypted_data_ss.as_ref());
Hmac::from_engine(hmac).to_byte_array()
};
pk.mul_tweak(
$secp_ctx,
&Scalar::from_be_bytes(hop_pk_blinding_factor).unwrap(),
)?
pk.mul_tweak($secp_ctx, &Scalar::from_be_bytes(hop_pk_blinding_factor).unwrap())
.expect("RNG is busted")
};
let onion_packet_ss = SharedSecret::new(&blinded_hop_pk, &onion_packet_pubkey_priv);

Expand Down Expand Up @@ -84,9 +82,9 @@ macro_rules! build_keys_helper {
Sha256::from_engine(sha).to_byte_array()
};

msg_blinding_point_priv = msg_blinding_point_priv.mul_tweak(
&Scalar::from_be_bytes(msg_blinding_point_blinding_factor).unwrap(),
)?;
msg_blinding_point_priv = msg_blinding_point_priv
.mul_tweak(&Scalar::from_be_bytes(msg_blinding_point_blinding_factor).unwrap())
.expect("RNG is busted");
msg_blinding_point =
PublicKey::from_secret_key($secp_ctx, &msg_blinding_point_priv);

Expand All @@ -96,9 +94,9 @@ macro_rules! build_keys_helper {
sha.input(onion_packet_ss.as_ref());
Sha256::from_engine(sha).to_byte_array()
};
onion_packet_pubkey_priv = onion_packet_pubkey_priv.mul_tweak(
&Scalar::from_be_bytes(onion_packet_pubkey_blinding_factor).unwrap(),
)?;
onion_packet_pubkey_priv = onion_packet_pubkey_priv
.mul_tweak(&Scalar::from_be_bytes(onion_packet_pubkey_blinding_factor).unwrap())
.expect("RNG is busted");
onion_packet_pubkey =
PublicKey::from_secret_key($secp_ctx, &onion_packet_pubkey_priv);
};
Expand All @@ -109,8 +107,7 @@ macro_rules! build_keys_helper {
pub(crate) fn construct_keys_for_onion_message<'a, T, I, F>(
secp_ctx: &Secp256k1<T>, unblinded_path: I, destination: Destination, session_priv: &SecretKey,
mut callback: F,
) -> Result<(), secp256k1::Error>
where
) where
T: secp256k1::Signing + secp256k1::Verification,
I: Iterator<Item = PublicKey>,
F: FnMut(SharedSecret, PublicKey, [u8; 32], Option<PublicKey>, Option<Vec<u8>>),
Expand All @@ -134,13 +131,11 @@ where
}
},
}
Ok(())
}

fn construct_keys_for_blinded_path<'a, T, I, F, H>(
secp_ctx: &Secp256k1<T>, unblinded_path: I, session_priv: &SecretKey, mut callback: F,
) -> Result<(), secp256k1::Error>
where
) where
T: secp256k1::Signing + secp256k1::Verification,
H: Borrow<PublicKey>,
I: Iterator<Item = H>,
Expand All @@ -151,7 +146,6 @@ where
for pk in unblinded_path {
build_keys_in_loop!(pk, false, None);
}
Ok(())
}

struct PublicKeyWithTlvs<W: Writeable> {
Expand All @@ -168,7 +162,7 @@ impl<W: Writeable> Borrow<PublicKey> for PublicKeyWithTlvs<W> {

pub(crate) fn construct_blinded_hops<'a, T, I, W>(
secp_ctx: &Secp256k1<T>, unblinded_path: I, session_priv: &SecretKey,
) -> Result<Vec<BlindedHop>, secp256k1::Error>
) -> Vec<BlindedHop>
where
T: secp256k1::Signing + secp256k1::Verification,
I: Iterator<Item = ((PublicKey, Option<ReceiveAuthKey>), W)>,
Expand All @@ -194,8 +188,8 @@ where
),
});
},
)?;
Ok(blinded_hops)
);
blinded_hops
}

/// Encrypt TLV payload to be used as a [`crate::blinded_path::BlindedHop::encrypted_payload`].
Expand Down
11 changes: 6 additions & 5 deletions lightning/src/ln/blinded_payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,7 @@ fn update_add_msg(
onion_routing_packet,
skimmed_fee_msat: None,
blinding_point,
hold_htlc: None,
}
}

Expand Down Expand Up @@ -1552,7 +1553,7 @@ fn route_blinding_spec_test_vector() {
];
let mut dave_eve_blinded_hops = blinded_path::utils::construct_blinded_hops(
&secp_ctx, path.into_iter(), &dave_eve_session_priv,
).unwrap();
);

// Concatenate an additional Bob -> Carol blinded path to the Eve -> Dave blinded path.
let bob_carol_session_priv = secret_from_hex("0202020202020202020202020202020202020202020202020202020202020202");
Expand All @@ -1563,7 +1564,7 @@ fn route_blinding_spec_test_vector() {
];
let bob_carol_blinded_hops = blinded_path::utils::construct_blinded_hops(
&secp_ctx, path.into_iter(), &bob_carol_session_priv,
).unwrap();
);

let mut blinded_hops = bob_carol_blinded_hops;
blinded_hops.append(&mut dave_eve_blinded_hops);
Expand Down Expand Up @@ -2030,7 +2031,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
let path = [((carol_node_id, None), WithoutLength(&carol_unblinded_tlvs))];
blinded_path::utils::construct_blinded_hops(
&secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv,
).unwrap()
)
} else {
let payee_tlvs = blinded_path::payment::TrampolineForwardTlvs {
next_trampoline: alice_node_id,
Expand All @@ -2051,7 +2052,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
let path = [((carol_node_id, None), WithoutLength(&carol_unblinded_tlvs))];
blinded_path::utils::construct_blinded_hops(
&secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv,
).unwrap()
)
};

let route = Route {
Expand Down Expand Up @@ -2255,7 +2256,7 @@ fn test_trampoline_unblinded_receive() {
let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv);
let carol_blinded_hops = blinded_path::utils::construct_blinded_hops(
&secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv,
).unwrap();
);

let route = Route {
paths: vec![Path {
Expand Down
Loading
Loading