Skip to content

Commit c1e860f

Browse files
committed
Provide our peers with SCID aliases and forward payments with them
This creates an SCID alias for all of our outbound channels, which we send to our counterparties as a part of the `funding_locked` message and then recognize in any HTLC forwarding instructions. Note that we generate an SCID alias for all channels, including already open ones, even though we currently have no way of communicating to our peers the SCID alias for already-open channels.
1 parent ec9fefe commit c1e860f

File tree

6 files changed

+199
-64
lines changed

6 files changed

+199
-64
lines changed

lightning/src/ln/channel.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,11 @@ pub(super) struct Channel<Signer: Sign> {
702702
// We only bother storing the most recent SCID alias at any time, though our counterparty has
703703
// to store all of them.
704704
latest_inbound_scid_alias: Option<u64>,
705+
// We always offer our counterparty a static SCID alias, which we recognize as for this channel
706+
// if we see it in HTLC forwarding instructions. We don't bother rotating the alias given we
707+
// don't currently support node id aliases and eventually privacy should be provided with
708+
// blinded paths instead of simple scid+node_id aliases.
709+
outbound_scid_alias: u64,
705710
}
706711

707712
#[cfg(any(test, feature = "fuzztarget"))]
@@ -807,7 +812,8 @@ impl<Signer: Sign> Channel<Signer> {
807812
// Constructors:
808813
pub fn new_outbound<K: Deref, F: Deref>(
809814
fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
810-
channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig, current_chain_height: u32
815+
channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig, current_chain_height: u32,
816+
outbound_scid_alias: u64
811817
) -> Result<Channel<Signer>, APIError>
812818
where K::Target: KeysInterface<Signer = Signer>,
813819
F::Target: FeeEstimator,
@@ -955,6 +961,7 @@ impl<Signer: Sign> Channel<Signer> {
955961
workaround_lnd_bug_4006: None,
956962

957963
latest_inbound_scid_alias: None,
964+
outbound_scid_alias,
958965

959966
#[cfg(any(test, feature = "fuzztarget"))]
960967
historical_inbound_htlc_fulfills: HashSet::new(),
@@ -993,7 +1000,8 @@ impl<Signer: Sign> Channel<Signer> {
9931000
/// Assumes chain_hash has already been checked and corresponds with what we expect!
9941001
pub fn new_from_req<K: Deref, F: Deref, L: Deref>(
9951002
fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures,
996-
msg: &msgs::OpenChannel, user_id: u64, config: &UserConfig, current_chain_height: u32, logger: &L
1003+
msg: &msgs::OpenChannel, user_id: u64, config: &UserConfig, current_chain_height: u32, logger: &L,
1004+
outbound_scid_alias: u64
9971005
) -> Result<Channel<Signer>, ChannelError>
9981006
where K::Target: KeysInterface<Signer = Signer>,
9991007
F::Target: FeeEstimator,
@@ -1262,6 +1270,7 @@ impl<Signer: Sign> Channel<Signer> {
12621270
workaround_lnd_bug_4006: None,
12631271

12641272
latest_inbound_scid_alias: None,
1273+
outbound_scid_alias,
12651274

12661275
#[cfg(any(test, feature = "fuzztarget"))]
12671276
historical_inbound_htlc_fulfills: HashSet::new(),
@@ -3467,7 +3476,7 @@ impl<Signer: Sign> Channel<Signer> {
34673476
Some(msgs::FundingLocked {
34683477
channel_id: self.channel_id(),
34693478
next_per_commitment_point,
3470-
short_channel_id_alias: None,
3479+
short_channel_id_alias: Some(self.outbound_scid_alias),
34713480
})
34723481
} else { None };
34733482

@@ -3689,7 +3698,7 @@ impl<Signer: Sign> Channel<Signer> {
36893698
funding_locked: Some(msgs::FundingLocked {
36903699
channel_id: self.channel_id(),
36913700
next_per_commitment_point,
3692-
short_channel_id_alias: None,
3701+
short_channel_id_alias: Some(self.outbound_scid_alias),
36933702
}),
36943703
raa: None, commitment_update: None, mon_update: None,
36953704
order: RAACommitmentOrder::CommitmentFirst,
@@ -3725,7 +3734,7 @@ impl<Signer: Sign> Channel<Signer> {
37253734
Some(msgs::FundingLocked {
37263735
channel_id: self.channel_id(),
37273736
next_per_commitment_point,
3728-
short_channel_id_alias: None,
3737+
short_channel_id_alias: Some(self.outbound_scid_alias),
37293738
})
37303739
} else { None };
37313740

@@ -4213,6 +4222,17 @@ impl<Signer: Sign> Channel<Signer> {
42134222
self.latest_inbound_scid_alias
42144223
}
42154224

4225+
/// Allowed in any state (including after shutdown)
4226+
pub fn get_outbound_scid_alias(&self) -> u64 {
4227+
self.outbound_scid_alias
4228+
}
4229+
/// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0,
4230+
/// indicating we were written by an old LDK which did not set outbound SCID aliases.
4231+
pub fn set_outbound_scid_alias(&mut self, outbound_scid_alias: u64) {
4232+
assert_eq!(self.outbound_scid_alias, 0);
4233+
self.outbound_scid_alias = outbound_scid_alias;
4234+
}
4235+
42164236
/// Returns the funding_txo we either got from our peer, or were given by
42174237
/// get_outbound_funding_created.
42184238
pub fn get_funding_txo(&self) -> Option<OutPoint> {
@@ -4465,7 +4485,7 @@ impl<Signer: Sign> Channel<Signer> {
44654485
return Some(msgs::FundingLocked {
44664486
channel_id: self.channel_id,
44674487
next_per_commitment_point,
4468-
short_channel_id_alias: None,
4488+
short_channel_id_alias: Some(self.outbound_scid_alias),
44694489
});
44704490
}
44714491
} else {
@@ -5784,6 +5804,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
57845804
(15, preimages, vec_type),
57855805
(17, self.announcement_sigs_state, required),
57865806
(19, self.latest_inbound_scid_alias, option),
5807+
(21, self.outbound_scid_alias, required),
57875808
});
57885809

57895810
Ok(())
@@ -6040,6 +6061,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
60406061
// AnnouncementSignatures" which implies we'll re-send it on reconnect, but that's fine.
60416062
let mut announcement_sigs_state = Some(AnnouncementSigsState::NotSent);
60426063
let mut latest_inbound_scid_alias = None;
6064+
let mut outbound_scid_alias = None;
60436065

60446066
read_tlv_fields!(reader, {
60456067
(0, announcement_sigs, option),
@@ -6056,6 +6078,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
60566078
(15, preimages_opt, vec_type),
60576079
(17, announcement_sigs_state, option),
60586080
(19, latest_inbound_scid_alias, option),
6081+
(21, outbound_scid_alias, option),
60596082
});
60606083

60616084
if let Some(preimages) = preimages_opt {
@@ -6191,6 +6214,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
61916214
workaround_lnd_bug_4006: None,
61926215

61936216
latest_inbound_scid_alias,
6217+
// Later in the ChannelManager deserialization phase we scan for channels and assign scid aliases if its missing
6218+
outbound_scid_alias: outbound_scid_alias.unwrap_or(0),
61946219

61956220
#[cfg(any(test, feature = "fuzztarget"))]
61966221
historical_inbound_htlc_fulfills,
@@ -6314,7 +6339,7 @@ mod tests {
63146339
let secp_ctx = Secp256k1::new();
63156340
let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
63166341
let config = UserConfig::default();
6317-
match Channel::<EnforcingSigner>::new_outbound(&&fee_estimator, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0) {
6342+
match Channel::<EnforcingSigner>::new_outbound(&&fee_estimator, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42) {
63186343
Err(APIError::IncompatibleShutdownScript { script }) => {
63196344
assert_eq!(script.into_inner(), non_v0_segwit_shutdown_script.into_inner());
63206345
},
@@ -6336,7 +6361,7 @@ mod tests {
63366361

63376362
let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
63386363
let config = UserConfig::default();
6339-
let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap();
6364+
let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
63406365

63416366
// Now change the fee so we can check that the fee in the open_channel message is the
63426367
// same as the old fee.
@@ -6362,13 +6387,13 @@ mod tests {
63626387
// Create Node A's channel pointing to Node B's pubkey
63636388
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
63646389
let config = UserConfig::default();
6365-
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap();
6390+
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
63666391

63676392
// Create Node B's channel by receiving Node A's open_channel message
63686393
// Make sure A's dust limit is as we expect.
63696394
let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash());
63706395
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
6371-
let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger).unwrap();
6396+
let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
63726397

63736398
// Node B --> Node A: accept channel, explicitly setting B's dust limit.
63746399
let mut accept_channel_msg = node_b_chan.accept_inbound_channel();
@@ -6432,7 +6457,7 @@ mod tests {
64326457

64336458
let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
64346459
let config = UserConfig::default();
6435-
let mut chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap();
6460+
let mut chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
64366461

64376462
let commitment_tx_fee_0_htlcs = Channel::<EnforcingSigner>::commit_tx_fee_msat(chan.feerate_per_kw, 0, chan.opt_anchors());
64386463
let commitment_tx_fee_1_htlc = Channel::<EnforcingSigner>::commit_tx_fee_msat(chan.feerate_per_kw, 1, chan.opt_anchors());
@@ -6481,12 +6506,12 @@ mod tests {
64816506
// Create Node A's channel pointing to Node B's pubkey
64826507
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
64836508
let config = UserConfig::default();
6484-
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap();
6509+
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
64856510

64866511
// Create Node B's channel by receiving Node A's open_channel message
64876512
let open_channel_msg = node_a_chan.get_open_channel(chain_hash);
64886513
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
6489-
let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger).unwrap();
6514+
let mut node_b_chan = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap();
64906515

64916516
// Node B --> Node A: accept channel
64926517
let accept_channel_msg = node_b_chan.accept_inbound_channel();
@@ -6543,7 +6568,7 @@ mod tests {
65436568
// Create a channel.
65446569
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
65456570
let config = UserConfig::default();
6546-
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap();
6571+
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap();
65476572
assert!(node_a_chan.counterparty_forwarding_info.is_none());
65486573
assert_eq!(node_a_chan.holder_htlc_minimum_msat, 1); // the default
65496574
assert!(node_a_chan.counterparty_forwarding_info().is_none());
@@ -6608,7 +6633,7 @@ mod tests {
66086633
let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
66096634
let mut config = UserConfig::default();
66106635
config.channel_options.announced_channel = false;
6611-
let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, &InitFeatures::known(), 10_000_000, 100000, 42, &config, 0).unwrap(); // Nothing uses their network key in this test
6636+
let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, &InitFeatures::known(), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test
66126637
chan.holder_dust_limit_satoshis = 546;
66136638
chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel
66146639

0 commit comments

Comments
 (0)