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.
type Signer : Sign;
- /// Get node secret key (aka node_id or network_key).
+ /// Get node secret key (aka node_id or network_key) based on the provided [`Recipient`].
///
- /// This method must return the same value each time it is called.
- fn get_node_secret(&self) -> SecretKey;
+ /// This method must return the same value each time it is called with a given `Recipient`
+ /// parameter.
+ fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()>;
/// Get a script pubkey which we send funds to when claiming on-chain contestable outputs.
///
/// This method should return a different value each time it is called, to avoid linking
/// 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.
///
impl KeysInterface for KeysManager {
type Signer = InMemorySigner;
- fn get_node_secret(&self) -> SecretKey {
- self.node_secret.clone()
+ fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
+ match recipient {
+ Recipient::Node => Ok(self.node_secret.clone()),
+ Recipient::PhantomNode => Err(())
+ }
}
fn get_inbound_payment_key_material(&self) -> KeyMaterial {
}
fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError> {
- InMemorySigner::read(&mut io::Cursor::new(reader), self.get_node_secret())
+ InMemorySigner::read(&mut io::Cursor::new(reader), self.node_secret.clone())
}
- 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::Node)?,
+ Recipient::PhantomNode => return Err(()),
+ };
+ Ok(self.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
}
}
impl KeysInterface for PhantomKeysManager {
type Signer = InMemorySigner;
- fn get_node_secret(&self) -> SecretKey {
- self.inner.get_node_secret()
+ fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
+ match recipient {
+ Recipient::Node => self.inner.get_node_secret(Recipient::Node),
+ Recipient::PhantomNode => Ok(self.phantom_secret.clone()),
+ }
}
fn get_inbound_payment_key_material(&self) -> KeyMaterial {
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 = self.get_node_secret(recipient)?;
+ Ok(self.inner.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
}
}