@@ -31,6 +31,7 @@ use bitcoin::secp256k1::recovery::RecoverableSignature;
31
31
use bitcoin:: secp256k1;
32
32
33
33
use util:: { byte_utils, transaction_utils} ;
34
+ use util:: crypto:: hkdf_extract_expand_twice;
34
35
use util:: ser:: { Writeable , Writer , Readable , ReadableArgs } ;
35
36
36
37
use chain:: transaction:: OutPoint ;
@@ -427,7 +428,16 @@ pub trait KeysInterface {
427
428
428
429
/// Get secret key material as bytes for use in encrypting and decrypting inbound payment data.
429
430
///
431
+ /// If the implementor of this trait supports [phantom node payments], then every node that is
432
+ /// intended to be included in the phantom invoice route hints must return the same value from
433
+ /// this method.
434
+ // This is because LDK avoids storing inbound payment data by encrypting payment data in the
435
+ // payment hash and/or payment secret, therefore for a payment to be receivable by multiple
436
+ // nodes, they must share the key that encrypts this payment data.
437
+ ///
430
438
/// This method must return the same value each time it is called.
439
+ ///
440
+ /// [phantom node payments]: PhantomKeysManager
431
441
fn get_inbound_payment_key_material ( & self ) -> KeyMaterial ;
432
442
}
433
443
@@ -810,6 +820,12 @@ impl ReadableArgs<SecretKey> for InMemorySigner {
810
820
/// ChannelMonitor closes may use seed/1'
811
821
/// Cooperative closes may use seed/2'
812
822
/// The two close keys may be needed to claim on-chain funds!
823
+ ///
824
+ /// This struct cannot be used for nodes that wish to support receiving phantom payments;
825
+ /// [`PhantomKeysManager`] must be used instead.
826
+ ///
827
+ /// Note that switching between this struct and [`PhantomKeysManager`] will invalidate any
828
+ /// previously issued invoices and attempts to pay previous invoices will fail.
813
829
pub struct KeysManager {
814
830
secp_ctx : Secp256k1 < secp256k1:: All > ,
815
831
node_secret : SecretKey ,
@@ -964,7 +980,7 @@ impl KeysManager {
964
980
/// transaction will have a feerate, at least, of the given value.
965
981
///
966
982
/// Returns `Err(())` if the output value is greater than the input value minus required fee,
967
- /// if a descriptor was duplicated, or if an output descriptor script_pubkey
983
+ /// if a descriptor was duplicated, or if an output descriptor ` script_pubkey`
968
984
/// does not match the one we can spend.
969
985
///
970
986
/// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
@@ -1139,6 +1155,102 @@ impl KeysInterface for KeysManager {
1139
1155
}
1140
1156
}
1141
1157
1158
+ /// Similar to [`KeysManager`], but allows the node using this struct to receive phantom node
1159
+ /// payments.
1160
+ ///
1161
+ /// A phantom node payment is a payment made to a phantom invoice, which is an invoice that can be
1162
+ /// paid to one of multiple nodes. This works because we encode the invoice route hints such that
1163
+ /// LDK will recognize an incoming payment as destined for a phantom node, and collect the payment
1164
+ /// itself without ever needing to forward to this fake node.
1165
+ ///
1166
+ /// Phantom node payments are useful for load balancing between multiple LDK nodes. They also
1167
+ /// provide some fault tolerance, because payers will automatically retry paying other provided
1168
+ /// nodes in the case that one node goes down.
1169
+ ///
1170
+ /// Note that multi-path payments are not supported in phantom invoices for security reasons.
1171
+ // In the hypothetical case that we did support MPP phantom payments, there would be no way for
1172
+ // nodes to know when the full payment has been received (and the preimage can be released) without
1173
+ // significantly compromising on our safety guarantees. I.e., if we expose the ability for the user
1174
+ // to tell LDK when the preimage can be released, we open ourselves to attacks where the preimage
1175
+ // is released too early.
1176
+ //
1177
+ /// Switching between this struct and [`KeysManager`] will invalidate any previously issued
1178
+ /// invoices and attempts to pay previous invoices will fail.
1179
+ pub struct PhantomKeysManager {
1180
+ inner : KeysManager ,
1181
+ inbound_payment_key : KeyMaterial ,
1182
+ phantom_secret : SecretKey ,
1183
+ }
1184
+
1185
+ impl KeysInterface for PhantomKeysManager {
1186
+ type Signer = InMemorySigner ;
1187
+
1188
+ fn get_node_secret ( & self ) -> SecretKey {
1189
+ self . inner . get_node_secret ( )
1190
+ }
1191
+
1192
+ fn get_inbound_payment_key_material ( & self ) -> KeyMaterial {
1193
+ self . inbound_payment_key . clone ( )
1194
+ }
1195
+
1196
+ fn get_destination_script ( & self ) -> Script {
1197
+ self . inner . get_destination_script ( )
1198
+ }
1199
+
1200
+ fn get_shutdown_scriptpubkey ( & self ) -> ShutdownScript {
1201
+ self . inner . get_shutdown_scriptpubkey ( )
1202
+ }
1203
+
1204
+ fn get_channel_signer ( & self , inbound : bool , channel_value_satoshis : u64 ) -> Self :: Signer {
1205
+ self . inner . get_channel_signer ( inbound, channel_value_satoshis)
1206
+ }
1207
+
1208
+ fn get_secure_random_bytes ( & self ) -> [ u8 ; 32 ] {
1209
+ self . inner . get_secure_random_bytes ( )
1210
+ }
1211
+
1212
+ fn read_chan_signer ( & self , reader : & [ u8 ] ) -> Result < Self :: Signer , DecodeError > {
1213
+ self . inner . read_chan_signer ( reader)
1214
+ }
1215
+
1216
+ fn sign_invoice ( & self , hrp_bytes : & [ u8 ] , invoice_data : & [ u5 ] ) -> Result < RecoverableSignature , ( ) > {
1217
+ let preimage = construct_invoice_preimage ( & hrp_bytes, & invoice_data) ;
1218
+ Ok ( self . inner . secp_ctx . sign_recoverable ( & hash_to_message ! ( & Sha256 :: hash( & preimage) ) , & self . get_node_secret ( ) ) )
1219
+ }
1220
+ }
1221
+
1222
+ impl PhantomKeysManager {
1223
+ /// Constructs a `PhantomKeysManager` given a 32-byte seed and an additional `cross_node_seed`
1224
+ /// that is shared across all nodes that intend to participate in [phantom node payments] together.
1225
+ ///
1226
+ /// See [`KeysManager::new`] for more information on `seed`, `starting_time_secs`, and
1227
+ /// `starting_time_nanos`.
1228
+ ///
1229
+ /// `cross_node_seed` must be the same across all phantom payment-receiving nodes and also the
1230
+ /// same across restarts, or else inbound payments may fail.
1231
+ ///
1232
+ /// [phantom node payments]: PhantomKeysManager
1233
+ pub fn new ( seed : & [ u8 ; 32 ] , starting_time_secs : u64 , starting_time_nanos : u32 , cross_node_seed : & [ u8 ; 32 ] ) -> Self {
1234
+ let inner = KeysManager :: new ( seed, starting_time_secs, starting_time_nanos) ;
1235
+ let ( inbound_key, phantom_key) = hkdf_extract_expand_twice ( b"LDK Inbound and Phantom Payment Key Expansion" , cross_node_seed) ;
1236
+ Self {
1237
+ inner,
1238
+ inbound_payment_key : KeyMaterial ( inbound_key) ,
1239
+ phantom_secret : SecretKey :: from_slice ( & phantom_key) . unwrap ( ) ,
1240
+ }
1241
+ }
1242
+
1243
+ /// See [`KeysManager::spend_spendable_outputs`] for documentation on this method.
1244
+ pub fn spend_spendable_outputs < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : Script , feerate_sat_per_1000_weight : u32 , secp_ctx : & Secp256k1 < C > ) -> Result < Transaction , ( ) > {
1245
+ self . inner . spend_spendable_outputs ( descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, secp_ctx)
1246
+ }
1247
+
1248
+ /// See [`KeysManager::derive_channel_keys`] for documentation on this method.
1249
+ pub fn derive_channel_keys ( & self , channel_value_satoshis : u64 , params : & [ u8 ; 32 ] ) -> InMemorySigner {
1250
+ self . inner . derive_channel_keys ( channel_value_satoshis, params)
1251
+ }
1252
+ }
1253
+
1142
1254
// Ensure that BaseSign can have a vtable
1143
1255
#[ test]
1144
1256
pub fn dyn_sign ( ) {
0 commit comments