nostr_types/types/
signature.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::{Error, Event};
use derive_more::{AsMut, AsRef, Deref, Display, From, FromStr, Into};
use serde::{Deserialize, Serialize};
#[cfg(feature = "speedy")]
use speedy::{Context, Readable, Reader, Writable, Writer};

/// A Schnorr signature that signs an Event, taken on the Event Id field
#[derive(
    AsMut, AsRef, Clone, Copy, Debug, Deref, Eq, From, Into, PartialEq, Serialize, Deserialize,
)]
pub struct Signature(pub secp256k1::schnorr::Signature);

impl Signature {
    /// Render into a hexadecimal string
    pub fn as_hex_string(&self) -> String {
        hex::encode(self.0.as_ref())
    }

    /// Create from a hexadecimal string
    pub fn try_from_hex_string(v: &str) -> Result<Signature, Error> {
        let vec: Vec<u8> = hex::decode(v)?;
        Ok(Signature(secp256k1::schnorr::Signature::from_slice(&vec)?))
    }

    /// A dummy signature of all zeroes
    pub fn zeroes() -> Signature {
        Signature(secp256k1::schnorr::Signature::from_slice(&[0; 64]).unwrap())
    }

    // Mock data for testing
    #[allow(dead_code)]
    pub(crate) fn mock() -> Signature {
        let event = Event::mock();
        event.sig
    }
}

#[cfg(feature = "speedy")]
impl<'a, C: Context> Readable<'a, C> for Signature {
    #[inline]
    fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, C::Error> {
        let bytes: Vec<u8> = reader.read_vec(64)?;
        let sig =
            secp256k1::schnorr::Signature::from_slice(&bytes[..]).map_err(speedy::Error::custom)?;
        Ok(Signature(sig))
    }

    #[inline]
    fn minimum_bytes_needed() -> usize {
        64
    }
}

#[cfg(feature = "speedy")]
impl<C: Context> Writable<C> for Signature {
    #[inline]
    fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
        let bytes = self.0.as_ref();
        assert_eq!(bytes.as_slice().len(), 64);
        writer.write_bytes(bytes.as_slice())
    }

    #[inline]
    fn bytes_needed(&self) -> Result<usize, C::Error> {
        Ok(64)
    }
}

/// A Schnorr signature that signs an Event, taken on the Event Id field, as a hex string
#[derive(
    AsMut,
    AsRef,
    Clone,
    Debug,
    Deref,
    Deserialize,
    Display,
    Eq,
    From,
    FromStr,
    Hash,
    Into,
    PartialEq,
    Serialize,
)]
#[cfg_attr(feature = "speedy", derive(Readable, Writable))]
pub struct SignatureHex(pub String);

impl SignatureHex {
    // Mock data for testing
    #[allow(dead_code)]
    pub(crate) fn mock() -> SignatureHex {
        From::from(Signature::mock())
    }
}

impl From<Signature> for SignatureHex {
    fn from(s: Signature) -> SignatureHex {
        SignatureHex(s.as_hex_string())
    }
}

impl TryFrom<SignatureHex> for Signature {
    type Error = Error;

    fn try_from(sh: SignatureHex) -> Result<Signature, Error> {
        Signature::try_from_hex_string(&sh.0)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    test_serde! {Signature, test_signature_serde}

    #[cfg(feature = "speedy")]
    #[test]
    fn test_speedy_signature() {
        let sig = Signature::mock();
        let bytes = sig.write_to_vec().unwrap();
        let sig2 = Signature::read_from_buffer(&bytes).unwrap();
        assert_eq!(sig, sig2);
    }
}