Skip to content

Commit af57d6d

Browse files
keysmanager: support phantom payments (aka multi-receive payments)
To support the feature of generating invoices that can be paid to any of multiple nodes, KeysManagers need to be able to share an inbound_payment_key and phantom secret key
1 parent e7cb8bf commit af57d6d

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use bitcoin::secp256k1::recovery::RecoverableSignature;
3030
use bitcoin::secp256k1;
3131

3232
use util::{byte_utils, transaction_utils};
33+
use util::crypto::hkdf_extract_expand;
3334
use util::ser::{Writeable, Writer, Readable};
3435

3536
use chain::transaction::OutPoint;
@@ -787,6 +788,7 @@ pub struct KeysManager {
787788
secp_ctx: Secp256k1<secp256k1::All>,
788789
node_secret: SecretKey,
789790
inbound_payment_key: KeyMaterial,
791+
phantom_secret: Option<SecretKey>,
790792
destination_script: Script,
791793
shutdown_pubkey: PublicKey,
792794
channel_master_key: ExtendedPrivKey,
@@ -821,7 +823,21 @@ impl KeysManager {
821823
/// Note that until the 0.1 release there is no guarantee of backward compatibility between
822824
/// versions. Once the library is more fully supported, the docs will be updated to include a
823825
/// detailed description of the guarantee.
826+
///
827+
/// This method cannot be used for nodes that wish to support receiving multi-node or phantom
828+
/// payments; [`KeysManager::new_multi_receive`] must be used instead.
824829
pub fn new(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self {
830+
Self::new_inner(seed, starting_time_secs, starting_time_nanos, None)
831+
}
832+
833+
/// Similar to [`KeysManager::new`], but allows the node using this `KeysManager` to receive
834+
/// phantom node payments. `cross_node_seed` must be the same across all phantom-receiving nodes
835+
/// and also the same across restarts, or else payments may fail.
836+
pub fn new_multi_receive(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32, cross_node_seed: &[u8; 32]) -> Self {
837+
Self::new_inner(seed, starting_time_secs, starting_time_nanos, Some(cross_node_seed))
838+
}
839+
840+
fn new_inner(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32, cross_node_seed: Option<&[u8; 32]>) -> Self {
825841
let secp_ctx = Secp256k1::new();
826842
// Note that when we aren't serializing the key, network doesn't matter
827843
match ExtendedPrivKey::new_master(Network::Testnet, seed) {
@@ -842,9 +858,15 @@ impl KeysManager {
842858
};
843859
let channel_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3).unwrap()).expect("Your RNG is busted");
844860
let rand_bytes_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(4).unwrap()).expect("Your RNG is busted");
845-
let inbound_payment_key: SecretKey = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5).unwrap()).expect("Your RNG is busted").private_key.key;
846-
let mut inbound_pmt_key_bytes = [0; 32];
847-
inbound_pmt_key_bytes.copy_from_slice(&inbound_payment_key[..]);
861+
let (inbound_payment_key, phantom_secret) = if let Some(key) = cross_node_seed {
862+
let hkdf = hkdf_extract_expand(b"LDK Inbound and Phantom Payment Key Expansion", key, 2);
863+
(KeyMaterial(hkdf[0]), Some(SecretKey::from_slice(&hkdf[1]).unwrap()))
864+
} else {
865+
let inbound_payment_key: SecretKey = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5).unwrap()).expect("Your RNG is busted").private_key.key;
866+
let mut inbound_pmt_key_bytes = [0; 32];
867+
inbound_pmt_key_bytes.copy_from_slice(&inbound_payment_key[..]);
868+
(KeyMaterial(inbound_pmt_key_bytes), None)
869+
};
848870

849871
let mut rand_bytes_unique_start = Sha256::engine();
850872
rand_bytes_unique_start.input(&byte_utils::be64_to_array(starting_time_secs));
@@ -854,7 +876,8 @@ impl KeysManager {
854876
let mut res = KeysManager {
855877
secp_ctx,
856878
node_secret,
857-
inbound_payment_key: KeyMaterial(inbound_pmt_key_bytes),
879+
inbound_payment_key,
880+
phantom_secret,
858881

859882
destination_script,
860883
shutdown_pubkey,

0 commit comments

Comments
 (0)