From: Valentine Wallace Date: Tue, 1 Feb 2022 22:33:57 +0000 (-0500) Subject: KeysInterface::sign_invoice: indicate whether invoice is a phantom X-Git-Tag: v0.0.105~13^2~6 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=f6c75d8ec3e3f3f4decb2397352ddc82ad165e38;p=rust-lightning KeysInterface::sign_invoice: indicate whether invoice is a phantom --- diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 8c11ba2c..2f526c68 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -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 { + fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { unreachable!() } } diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 9db04b64..74aa5f1c 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -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 { + fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { unreachable!() } } diff --git a/lightning-invoice/src/utils.rs b/lightning-invoice/src/utils.rs index ef95b3e3..1b55c34e 100644 --- a/lightning-invoice/src/utils.rs +++ b/lightning-invoice/src/utils.rs @@ -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)) diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index f5ba6bc3..04537b7a 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -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; + /// + /// 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; /// 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 { + fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { 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 { + fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { 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)) } } diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index ed7975fe..5ce0df13 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -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 { panic!(); } - fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result { panic!(); } + fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { panic!(); } } fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 0e1c92d0..dcfe6527 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -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); 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 { unreachable!(); } + fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { 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 { - self.backing.sign_invoice(hrp_bytes, invoice_data) + fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { + self.backing.sign_invoice(hrp_bytes, invoice_data, recipient) } }