KeysInterface::sign_invoice: indicate whether invoice is a phantom
authorValentine Wallace <vwallace@protonmail.com>
Tue, 1 Feb 2022 22:33:57 +0000 (17:33 -0500)
committerValentine Wallace <vwallace@protonmail.com>
Mon, 14 Feb 2022 19:22:38 +0000 (14:22 -0500)
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
lightning-invoice/src/utils.rs
lightning/src/chain/keysinterface.rs
lightning/src/ln/channel.rs
lightning/src/util/test_utils.rs

index 8c11ba2c6c712aba66604a62861416dbd3a551e5..2f526c68f5527679ed884d847fa298805c503bc4 100644 (file)
@@ -34,7 +34,7 @@ use lightning::chain::{BestBlock, ChannelMonitorUpdateErr, chainmonitor, channel
 use lightning::chain::channelmonitor::{ChannelMonitor, MonitorEvent};
 use lightning::chain::transaction::OutPoint;
 use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
-use lightning::chain::keysinterface::{KeyMaterial, KeysInterface, InMemorySigner};
+use lightning::chain::keysinterface::{KeyMaterial, KeysInterface, InMemorySigner, Recipient};
 use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs};
 use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
@@ -222,7 +222,7 @@ impl KeysInterface for KeyProvider {
                })
        }
 
-       fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result<RecoverableSignature, ()> {
+       fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
                unreachable!()
        }
 }
index 9db04b645e4143496a921eac2cd4a1d0bc83ae37..74aa5f1c6cfef8c88b204f57fd09ff0075ab72b9 100644 (file)
@@ -31,7 +31,7 @@ use lightning::chain::{BestBlock, Confirm, Listen};
 use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
 use lightning::chain::chainmonitor;
 use lightning::chain::transaction::OutPoint;
-use lightning::chain::keysinterface::{InMemorySigner, KeyMaterial, KeysInterface};
+use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface};
 use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 use lightning::ln::channelmanager::{ChainParameters, ChannelManager};
 use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,IgnoringMessageHandler};
@@ -336,7 +336,7 @@ impl KeysInterface for KeyProvider {
                ))
        }
 
-       fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result<RecoverableSignature, ()> {
+       fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
                unreachable!()
        }
 }
index ef95b3e355b5abd1c91303e3e708b2014041482a..1b55c34e444c79b2b44f26fe0ea81059ed518313 100644 (file)
@@ -8,7 +8,7 @@ use bitcoin_hashes::Hash;
 use crate::prelude::*;
 use lightning::chain;
 use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
-use lightning::chain::keysinterface::{Sign, KeysInterface};
+use lightning::chain::keysinterface::{Recipient, KeysInterface, Sign};
 use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, PaymentId, PaymentSendFailure, MIN_FINAL_CLTV_EXPIRY};
 use lightning::ln::msgs::LightningError;
@@ -118,7 +118,7 @@ where
        let hrp_str = raw_invoice.hrp.to_string();
        let hrp_bytes = hrp_str.as_bytes();
        let data_without_signature = raw_invoice.data.to_base32();
-       let signed_raw_invoice = raw_invoice.sign(|_| keys_manager.sign_invoice(hrp_bytes, &data_without_signature));
+       let signed_raw_invoice = raw_invoice.sign(|_| keys_manager.sign_invoice(hrp_bytes, &data_without_signature, Recipient::Node));
        match signed_raw_invoice {
                Ok(inv) => Ok(Invoice::from_signed(inv).unwrap()),
                Err(e) => Err(SignOrCreationError::SignError(e))
index f5ba6bc3e8f7c85a56e7a1aeceb372fc703bb103..04537b7a5a44c1a4d4af7e34fa8d1b608056a6c5 100644 (file)
@@ -380,6 +380,18 @@ pub trait BaseSign {
 pub trait Sign: BaseSign + Writeable + Clone {
 }
 
+/// Specifies the recipient of an invoice, to indicate to [`KeysInterface::sign_invoice`] what node
+/// secret key should be used to sign the invoice.
+pub enum Recipient {
+       /// The invoice should be signed with the local node secret key.
+       Node,
+       /// The invoice should be signed with the phantom node secret key. This secret key must be the
+       /// same for all nodes participating in the [phantom node payment].
+       ///
+       /// [phantom node payment]: PhantomKeysManager
+       PhantomNode,
+}
+
 /// A trait to describe an object which can get user secrets and key material.
 pub trait KeysInterface {
        /// A type which implements Sign which will be returned by get_channel_signer.
@@ -424,7 +436,9 @@ pub trait KeysInterface {
        /// this trait to parse the invoice and make sure they're signing what they expect, rather than
        /// blindly signing the hash.
        /// The hrp is ascii bytes, while the invoice data is base32.
-       fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5]) -> Result<RecoverableSignature, ()>;
+       ///
+       /// The secret key used to sign the invoice is dependent on the [`Recipient`].
+       fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], receipient: Recipient) -> Result<RecoverableSignature, ()>;
 
        /// Get secret key material as bytes for use in encrypting and decrypting inbound payment data.
        ///
@@ -1149,9 +1163,13 @@ impl KeysInterface for KeysManager {
                InMemorySigner::read(&mut io::Cursor::new(reader), self.get_node_secret())
        }
 
-       fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5]) -> Result<RecoverableSignature, ()> {
+       fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
                let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
-               Ok(self.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &self.get_node_secret()))
+               let secret = match recipient {
+                       Recipient::Node => self.get_node_secret(),
+                       Recipient::PhantomNode => return Err(()),
+               };
+               Ok(self.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
        }
 }
 
@@ -1213,9 +1231,13 @@ impl KeysInterface for PhantomKeysManager {
                self.inner.read_chan_signer(reader)
        }
 
-       fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5]) -> Result<RecoverableSignature, ()> {
+       fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
                let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
-               Ok(self.inner.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &self.get_node_secret()))
+               let secret = match recipient {
+                       Recipient::Node => self.get_node_secret(),
+                       Recipient::PhantomNode => self.phantom_secret.clone(),
+               };
+               Ok(self.inner.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
        }
 }
 
index ed7975fe9ca9311794cbc036c5f38f5d8c3881de..5ce0df13cb9c5f26fc8f8c786ebbb1ac176f005f 100644 (file)
@@ -6188,7 +6188,7 @@ mod tests {
        use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, htlc_success_tx_weight, htlc_timeout_tx_weight};
        use chain::BestBlock;
        use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
-       use chain::keysinterface::{InMemorySigner, KeyMaterial, KeysInterface, BaseSign};
+       use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface, BaseSign};
        use chain::transaction::OutPoint;
        use util::config::UserConfig;
        use util::enforcing_trait_impls::EnforcingSigner;
@@ -6256,7 +6256,7 @@ mod tests {
                }
                fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }
                fn read_chan_signer(&self, _data: &[u8]) -> Result<Self::Signer, DecodeError> { panic!(); }
-               fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result<RecoverableSignature, ()> { panic!(); }
+               fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { panic!(); }
        }
 
        fn public_from_secret_hex(secp_ctx: &Secp256k1<All>, hex: &str) -> PublicKey {
index 0e1c92d009c112cbc74c6f811a5fc9d158f56dd3..dcfe65278dbc3a4ff3294075ff8c096dc9557687 100644 (file)
@@ -47,7 +47,7 @@ use sync::{Mutex, Arc};
 use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
 use core::{cmp, mem};
 use bitcoin::bech32::u5;
-use chain::keysinterface::{InMemorySigner, KeyMaterial};
+use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial};
 
 pub struct TestVecWriter(pub Vec<u8>);
 impl Writer for TestVecWriter {
@@ -88,7 +88,7 @@ impl keysinterface::KeysInterface for OnlyReadsKeysInterface {
                        false
                ))
        }
-       fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result<RecoverableSignature, ()> { unreachable!(); }
+       fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { unreachable!(); }
 }
 
 pub struct TestChainMonitor<'a> {
@@ -529,8 +529,8 @@ impl keysinterface::KeysInterface for TestKeysInterface {
                ))
        }
 
-       fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5]) -> Result<RecoverableSignature, ()> {
-               self.backing.sign_invoice(hrp_bytes, invoice_data)
+       fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
+               self.backing.sign_invoice(hrp_bytes, invoice_data, recipient)
        }
 }