Support BOLT 12 signing in c_bindings
[rust-lightning] / lightning / src / offers / merkle.rs
index ced3b08b7c2f3a33becd7b2e4f2a444f909a66c9..5a9424500b37c8e037f22b0e9ea2ee7cd561c911 100644 (file)
@@ -76,13 +76,33 @@ impl AsRef<TaggedHash> for TaggedHash {
 
 /// Error when signing messages.
 #[derive(Debug, PartialEq)]
-pub enum SignError<E> {
+pub enum SignError<E = ()> {
        /// User-defined error when signing the message.
        Signing(E),
        /// Error when verifying the produced signature using the given pubkey.
        Verification(secp256k1::Error),
 }
 
+/// A function for signing a [`TaggedHash`].
+pub(super) trait SignFn<T: AsRef<TaggedHash>> {
+       /// Error type returned by the function.
+       type Error;
+
+       /// Signs a [`TaggedHash`] computed over the merkle root of `message`'s TLV stream.
+       fn sign(&self, message: &T) -> Result<Signature, Self::Error>;
+}
+
+impl<F, E> SignFn<TaggedHash> for F
+where
+       F: Fn(&TaggedHash) -> Result<Signature, E>,
+{
+       type Error = E;
+
+       fn sign(&self, message: &TaggedHash) -> Result<Signature, E> {
+               self(message)
+       }
+}
+
 /// Signs a [`TaggedHash`] computed over the merkle root of `message`'s TLV stream, checking if it
 /// can be verified with the supplied `pubkey`.
 ///
@@ -92,14 +112,14 @@ pub enum SignError<E> {
 ///
 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
-pub(super) fn sign_message<F, E, T>(
-       sign: F, message: &T, pubkey: PublicKey,
+pub(super) fn sign_message<F, T, E>(
+       f: F, message: &T, pubkey: PublicKey,
 ) -> Result<Signature, SignError<E>>
 where
-       F: FnOnce(&T) -> Result<Signature, E>,
+       F: SignFn<T, Error = E>,
        T: AsRef<TaggedHash>,
 {
-       let signature = sign(message).map_err(|e| SignError::Signing(e))?;
+       let signature = f.sign(message).map_err(|e| SignError::Signing(e))?;
 
        let digest = message.as_ref().as_digest();
        let pubkey = pubkey.into();
@@ -278,7 +298,7 @@ mod tests {
        use bitcoin::secp256k1::schnorr::Signature;
        use core::convert::Infallible;
        use crate::offers::offer::{Amount, OfferBuilder};
-       use crate::offers::invoice_request::InvoiceRequest;
+       use crate::offers::invoice_request::{InvoiceRequest, UnsignedInvoiceRequest};
        use crate::offers::parse::Bech32Encode;
        use crate::offers::test_utils::{payer_pubkey, recipient_pubkey};
        use crate::util::ser::Writeable;
@@ -321,9 +341,9 @@ mod tests {
                        .build_unchecked()
                        .request_invoice(vec![0; 8], payer_keys.public_key()).unwrap()
                        .build_unchecked()
-                       .sign::<_, Infallible>(
-                               |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
-                       )
+                       .sign(|message: &UnsignedInvoiceRequest| -> Result<_, Infallible> {
+                               Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
+                       })
                        .unwrap();
                assert_eq!(
                        invoice_request.to_string(),
@@ -375,9 +395,9 @@ mod tests {
                        .build_unchecked()
                        .request_invoice(vec![0; 8], payer_keys.public_key()).unwrap()
                        .build_unchecked()
-                       .sign::<_, Infallible>(
-                               |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
-                       )
+                       .sign(|message: &UnsignedInvoiceRequest| -> Result<_, Infallible> {
+                               Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
+                       })
                        .unwrap();
 
                let mut bytes_without_signature = Vec::new();
@@ -407,9 +427,9 @@ mod tests {
                        .build_unchecked()
                        .request_invoice(vec![0; 8], payer_keys.public_key()).unwrap()
                        .build_unchecked()
-                       .sign::<_, Infallible>(
-                               |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
-                       )
+                       .sign(|message: &UnsignedInvoiceRequest| -> Result<_, Infallible> {
+                               Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
+                       })
                        .unwrap();
 
                let tlv_stream = TlvStream::new(&invoice_request.bytes).range(0..1)