}
/// LDK has multiple reasons to generate fake short channel ids:
-/// 1) zero-conf channels that don't have a confirmed channel id yet
+/// 1) outbound SCID aliases we use for private channels
/// 2) phantom node payments, to get an scid for the phantom node's phantom channel
pub(crate) mod fake_scid {
use bitcoin::hash_types::BlockHash;
/// receipt, and handle the HTLC accordingly. The namespace identifier is encrypted when encoded
/// into the fake scid.
#[derive(Copy, Clone)]
- pub(super) enum Namespace {
+ pub(crate) enum Namespace {
Phantom,
- // Coming soon: a variant for the zero-conf scid namespace
+ OutboundAlias,
}
impl Namespace {
/// between segwit activation and the current best known height, and the tx index and output
/// index are also selected from a "reasonable" range. We add this logic because it makes it
/// non-obvious at a glance that the scid is fake, e.g. if it appears in invoice route hints.
- pub(super) fn get_fake_scid<Signer: Sign, K: Deref>(&self, highest_seen_blockheight: u32, genesis_hash: &BlockHash, fake_scid_rand_bytes: &[u8; 32], keys_manager: &K) -> u64
+ pub(crate) fn get_fake_scid<Signer: Sign, K: Deref>(&self, highest_seen_blockheight: u32, genesis_hash: &BlockHash, fake_scid_rand_bytes: &[u8; 32], keys_manager: &K) -> u64
where K::Target: KeysInterface<Signer = Signer>,
{
// Ensure we haven't created a namespace that doesn't fit into the 3 bits we've allocated for
let rand_bytes = keys_manager.get_secure_random_bytes();
let segwit_activation_height = segwit_activation_height(genesis_hash);
- let mut valid_block_range = if highest_seen_blockheight > segwit_activation_height {
- highest_seen_blockheight - segwit_activation_height
- } else {
- 1
- };
+ let mut blocks_since_segwit_activation = highest_seen_blockheight.saturating_sub(segwit_activation_height);
+
// We want to ensure that this fake channel won't conflict with any transactions we haven't
// seen yet, in case `highest_seen_blockheight` is updated before we get full information
// about transactions confirmed in the given block.
- if valid_block_range > BLOCKS_PER_MONTH { valid_block_range -= BLOCKS_PER_MONTH; }
+ blocks_since_segwit_activation = blocks_since_segwit_activation.saturating_sub(BLOCKS_PER_MONTH);
let rand_for_height = u32::from_be_bytes(rand_bytes[..4].try_into().unwrap());
- let fake_scid_height = segwit_activation_height + rand_for_height % valid_block_range;
+ let fake_scid_height = segwit_activation_height + rand_for_height % (blocks_since_segwit_activation + 1);
let rand_for_tx_index = u32::from_be_bytes(rand_bytes[4..8].try_into().unwrap());
let fake_scid_tx_index = rand_for_tx_index % MAX_TX_INDEX;
}
}
- pub fn get_phantom_scid<Signer: Sign, K: Deref>(fake_scid_rand_bytes: &[u8; 32], highest_seen_blockheight: u32, genesis_hash: &BlockHash, keys_manager: &K) -> u64
- where K::Target: KeysInterface<Signer = Signer>,
- {
- let namespace = Namespace::Phantom;
- namespace.get_fake_scid(highest_seen_blockheight, genesis_hash, fake_scid_rand_bytes, keys_manager)
- }
-
fn segwit_activation_height(genesis: &BlockHash) -> u32 {
const MAINNET_GENESIS_STR: &'static str = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f";
if BlockHash::from_hex(MAINNET_GENESIS_STR).unwrap() == *genesis {