nostr_types/types/
signature.rs

1use crate::{Error, Event};
2use derive_more::{AsMut, AsRef, Deref, Display, From, FromStr, Into};
3use serde::{Deserialize, Serialize};
4#[cfg(feature = "speedy")]
5use speedy::{Context, Readable, Reader, Writable, Writer};
6
7/// A Schnorr signature that signs an Event, taken on the Event Id field
8#[derive(
9    AsMut, AsRef, Clone, Copy, Debug, Deref, Eq, From, Into, PartialEq, Serialize, Deserialize,
10)]
11pub struct Signature(pub secp256k1::schnorr::Signature);
12
13impl Signature {
14    /// Render into a hexadecimal string
15    pub fn as_hex_string(&self) -> String {
16        hex::encode(self.0.as_ref())
17    }
18
19    /// Create from a hexadecimal string
20    pub fn try_from_hex_string(v: &str) -> Result<Signature, Error> {
21        let vec: Vec<u8> = hex::decode(v)?;
22        Ok(Signature(secp256k1::schnorr::Signature::from_slice(&vec)?))
23    }
24
25    /// A dummy signature of all zeroes
26    pub fn zeroes() -> Signature {
27        Signature(secp256k1::schnorr::Signature::from_slice(&[0; 64]).unwrap())
28    }
29
30    // Mock data for testing
31    #[allow(dead_code)]
32    pub(crate) async fn mock() -> Signature {
33        let event = Event::mock().await;
34        event.sig
35    }
36}
37
38#[cfg(feature = "speedy")]
39impl<'a, C: Context> Readable<'a, C> for Signature {
40    #[inline]
41    fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, C::Error> {
42        let bytes: Vec<u8> = reader.read_vec(64)?;
43        let sig =
44            secp256k1::schnorr::Signature::from_slice(&bytes[..]).map_err(speedy::Error::custom)?;
45        Ok(Signature(sig))
46    }
47
48    #[inline]
49    fn minimum_bytes_needed() -> usize {
50        64
51    }
52}
53
54#[cfg(feature = "speedy")]
55impl<C: Context> Writable<C> for Signature {
56    #[inline]
57    fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
58        let bytes = self.0.as_ref();
59        assert_eq!(bytes.as_slice().len(), 64);
60        writer.write_bytes(bytes.as_slice())
61    }
62
63    #[inline]
64    fn bytes_needed(&self) -> Result<usize, C::Error> {
65        Ok(64)
66    }
67}
68
69/// A Schnorr signature that signs an Event, taken on the Event Id field, as a hex string
70#[derive(
71    AsMut,
72    AsRef,
73    Clone,
74    Debug,
75    Deref,
76    Deserialize,
77    Display,
78    Eq,
79    From,
80    FromStr,
81    Hash,
82    Into,
83    PartialEq,
84    Serialize,
85)]
86#[cfg_attr(feature = "speedy", derive(Readable, Writable))]
87pub struct SignatureHex(pub String);
88
89impl SignatureHex {
90    // Mock data for testing
91    #[allow(dead_code)]
92    pub(crate) async fn mock() -> SignatureHex {
93        From::from(Signature::mock().await)
94    }
95}
96
97impl From<Signature> for SignatureHex {
98    fn from(s: Signature) -> SignatureHex {
99        SignatureHex(s.as_hex_string())
100    }
101}
102
103impl TryFrom<SignatureHex> for Signature {
104    type Error = Error;
105
106    fn try_from(sh: SignatureHex) -> Result<Signature, Error> {
107        Signature::try_from_hex_string(&sh.0)
108    }
109}
110
111#[cfg(test)]
112mod test {
113    use super::*;
114
115    test_serde_async! {Signature, test_signature_serde}
116
117    #[cfg(feature = "speedy")]
118    #[tokio::test]
119    async fn test_speedy_signature() {
120        let sig = Signature::mock().await;
121        let bytes = sig.write_to_vec().unwrap();
122        let sig2 = Signature::read_from_buffer(&bytes).unwrap();
123        assert_eq!(sig, sig2);
124    }
125}