From 3a1268e177feaaea01a38a5d3f2475f5f770ae9d Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 4 Nov 2022 11:54:57 -0400 Subject: [PATCH] Add fake scid namespace for intercepted HTLCs This is useful for LSPs who wish to create a just-in-time channel for end users receiving a lightning payment. These fake scids will be encoded into route hints in end user invoices, and signal to LDK to create an event triggering the JIT channel, after which the payment will be received. Co-authored-by: John Cantrell Co-authored-by: Valentine Wallace --- lightning/src/util/scid_utils.rs | 33 ++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/lightning/src/util/scid_utils.rs b/lightning/src/util/scid_utils.rs index 651b36ef3..1d951b8f9 100644 --- a/lightning/src/util/scid_utils.rs +++ b/lightning/src/util/scid_utils.rs @@ -63,6 +63,8 @@ pub fn scid_from_parts(block: u64, tx_index: u64, vout_index: u64) -> Result bool { let block_height = scid_utils::block_from_scid(&scid); let tx_index = scid_utils::tx_index_from_scid(&scid); @@ -160,11 +163,21 @@ pub(crate) mod fake_scid { && valid_vout == scid_utils::vout_from_scid(&scid) as u8 } + /// Returns whether the given fake scid falls into the intercept namespace. + pub fn is_valid_intercept(fake_scid_rand_bytes: &[u8; 32], scid: u64, genesis_hash: &BlockHash) -> bool { + let block_height = scid_utils::block_from_scid(&scid); + let tx_index = scid_utils::tx_index_from_scid(&scid); + let namespace = Namespace::Intercept; + let valid_vout = namespace.get_encrypted_vout(block_height, tx_index, fake_scid_rand_bytes); + block_height >= segwit_activation_height(genesis_hash) + && valid_vout == scid_utils::vout_from_scid(&scid) as u8 + } + #[cfg(test)] mod tests { use bitcoin::blockdata::constants::genesis_block; use bitcoin::network::constants::Network; - use crate::util::scid_utils::fake_scid::{is_valid_phantom, MAINNET_SEGWIT_ACTIVATION_HEIGHT, MAX_TX_INDEX, MAX_NAMESPACES, Namespace, NAMESPACE_ID_BITMASK, segwit_activation_height, TEST_SEGWIT_ACTIVATION_HEIGHT}; + use crate::util::scid_utils::fake_scid::{is_valid_intercept, is_valid_phantom, MAINNET_SEGWIT_ACTIVATION_HEIGHT, MAX_TX_INDEX, MAX_NAMESPACES, Namespace, NAMESPACE_ID_BITMASK, segwit_activation_height, TEST_SEGWIT_ACTIVATION_HEIGHT}; use crate::util::scid_utils; use crate::util::test_utils; use crate::sync::Arc; @@ -174,6 +187,10 @@ pub(crate) mod fake_scid { let phantom_namespace = Namespace::Phantom; assert!((phantom_namespace as u8) < MAX_NAMESPACES); assert!((phantom_namespace as u8) <= NAMESPACE_ID_BITMASK); + + let intercept_namespace = Namespace::Intercept; + assert!((intercept_namespace as u8) < MAX_NAMESPACES); + assert!((intercept_namespace as u8) <= NAMESPACE_ID_BITMASK); } #[test] @@ -203,6 +220,18 @@ pub(crate) mod fake_scid { assert!(!is_valid_phantom(&fake_scid_rand_bytes, invalid_fake_scid, &testnet_genesis)); } + #[test] + fn test_is_valid_intercept() { + let namespace = Namespace::Intercept; + let fake_scid_rand_bytes = [0; 32]; + let testnet_genesis = genesis_block(Network::Testnet).header.block_hash(); + let valid_encrypted_vout = namespace.get_encrypted_vout(0, 0, &fake_scid_rand_bytes); + let valid_fake_scid = scid_utils::scid_from_parts(1, 0, valid_encrypted_vout as u64).unwrap(); + assert!(is_valid_intercept(&fake_scid_rand_bytes, valid_fake_scid, &testnet_genesis)); + let invalid_fake_scid = scid_utils::scid_from_parts(1, 0, 12).unwrap(); + assert!(!is_valid_intercept(&fake_scid_rand_bytes, invalid_fake_scid, &testnet_genesis)); + } + #[test] fn test_get_fake_scid() { let mainnet_genesis = genesis_block(Network::Bitcoin).header.block_hash(); -- 2.39.5