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
use std::convert::TryFrom;
use std::marker::PhantomData;

use crate::{Binding, Domain, Error, SpendAuth};

/// A `decaf377-rdsa` signature.
#[derive(Copy, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(try_from = "&[u8]", into = "Vec<u8>"))]
pub struct Signature<D: Domain> {
    bytes: [u8; 64],
    _marker: PhantomData<D>,
}

impl<D: Domain> AsRef<[u8]> for Signature<D> {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

impl<D: Domain> Signature<D> {
    /// Returns the bytes of the signature.
    ///
    /// This is the same as `.into()`, but does not require type inference.
    pub fn to_bytes(&self) -> [u8; 64] {
        self.bytes
    }

    pub(crate) fn from_parts(r_bytes: [u8; 32], s_bytes: [u8; 32]) -> Self {
        let mut bytes = [0; 64];
        bytes[0..32].copy_from_slice(&r_bytes[..]);
        bytes[32..64].copy_from_slice(&s_bytes[..]);
        Self {
            bytes,
            _marker: PhantomData,
        }
    }

    pub(crate) fn r_bytes(&self) -> [u8; 32] {
        self.bytes[0..32].try_into().expect("32 byte array")
    }

    pub(crate) fn s_bytes(&self) -> [u8; 32] {
        self.bytes[32..64].try_into().expect("32 byte array")
    }
}

impl std::fmt::Debug for Signature<Binding> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("Signature<Binding>")
            .field(&hex::encode(&<[u8; 64]>::from(*self)))
            .finish()
    }
}

impl std::fmt::Debug for Signature<SpendAuth> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("Signature<SpendAuth>")
            .field(&hex::encode(&<[u8; 64]>::from(*self)))
            .finish()
    }
}

impl<D: Domain> From<[u8; 64]> for Signature<D> {
    fn from(bytes: [u8; 64]) -> Signature<D> {
        Signature {
            bytes,
            _marker: PhantomData,
        }
    }
}

impl<D: Domain> From<Signature<D>> for [u8; 64] {
    fn from(sig: Signature<D>) -> [u8; 64] {
        sig.to_bytes()
    }
}

impl<D: Domain> From<Signature<D>> for Vec<u8> {
    fn from(sig: Signature<D>) -> Vec<u8> {
        sig.to_bytes().into()
    }
}

impl<D: Domain> TryFrom<&[u8]> for Signature<D> {
    type Error = Error;

    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
        if bytes.len() == 64 {
            let mut bytes64 = [0u8; 64];
            bytes64.copy_from_slice(bytes);
            Ok(bytes64.into())
        } else {
            Err(Error::WrongSliceLength {
                expected: 64,
                found: bytes.len(),
            })
        }
    }
}

impl<D: Domain> TryFrom<Vec<u8>> for Signature<D> {
    type Error = Error;

    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
        value.as_slice().try_into()
    }
}

impl<D: Domain> std::cmp::PartialEq for Signature<D> {
    fn eq(&self, other: &Self) -> bool {
        self.bytes == other.bytes
    }
}

impl<D: Domain> std::cmp::Eq for Signature<D> {}