fuel_crypto/
message.rs

1use crate::Hasher;
2use core::{
3    fmt,
4    ops::Deref,
5};
6pub use fuel_types::Bytes32;
7
8/// Normalized (hashed) message authenticated by a signature
9#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[repr(transparent)]
12pub struct Message(Bytes32);
13
14impl Message {
15    /// Memory length of the type in bytes.
16    pub const LEN: usize = Bytes32::LEN;
17
18    /// Normalize the given message by cryptographically hashing its content in
19    /// preparation for signing.
20    pub fn new<M>(message: M) -> Self
21    where
22        M: AsRef<[u8]>,
23    {
24        Self(Hasher::hash(message))
25    }
26
27    /// Construct a `Message` directly from its bytes.
28    ///
29    /// This constructor expects the given bytes to be a valid,
30    /// cryptographically hashed message. No hashing is performed.
31    pub fn from_bytes(bytes: [u8; Self::LEN]) -> Self {
32        Self(bytes.into())
33    }
34
35    /// Construct a `Message` reference directly from a reference to its bytes.
36    ///
37    /// This constructor expects the given bytes to be a valid,
38    /// cryptographically hashed message. No hashing is performed.
39    pub fn from_bytes_ref(bytes: &[u8; Self::LEN]) -> &Self {
40        // TODO: Wrap this unsafe conversion safely in `fuel_types::Bytes32`.
41        #[allow(unsafe_code)]
42        unsafe {
43            &*(bytes.as_ptr() as *const Self)
44        }
45    }
46
47    /// Kept temporarily for backwards compatibility.
48    #[deprecated = "Use `Message::from_bytes` instead"]
49    pub fn from_bytes_unchecked(bytes: [u8; Self::LEN]) -> Self {
50        Self::from_bytes(bytes)
51    }
52}
53
54impl Deref for Message {
55    type Target = [u8; Message::LEN];
56
57    fn deref(&self) -> &[u8; Message::LEN] {
58        self.0.deref()
59    }
60}
61
62impl AsRef<[u8]> for Message {
63    fn as_ref(&self) -> &[u8] {
64        self.0.as_ref()
65    }
66}
67
68impl From<Message> for [u8; Message::LEN] {
69    fn from(message: Message) -> [u8; Message::LEN] {
70        message.0.into()
71    }
72}
73
74impl From<Message> for Bytes32 {
75    fn from(s: Message) -> Self {
76        s.0
77    }
78}
79
80impl From<&Hasher> for Message {
81    fn from(hasher: &Hasher) -> Self {
82        // Safety: `Hasher` is a cryptographic hash
83        Self::from_bytes(*hasher.digest())
84    }
85}
86
87impl From<Hasher> for Message {
88    fn from(hasher: Hasher) -> Self {
89        // Safety: `Hasher` is a cryptographic hash
90        Self::from_bytes(*hasher.finalize())
91    }
92}
93
94impl fmt::LowerHex for Message {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96        self.0.fmt(f)
97    }
98}
99
100impl fmt::UpperHex for Message {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        self.0.fmt(f)
103    }
104}
105
106impl fmt::Debug for Message {
107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108        self.0.fmt(f)
109    }
110}
111
112impl fmt::Display for Message {
113    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114        self.0.fmt(f)
115    }
116}
117
118#[cfg(feature = "std")]
119impl From<&Message> for secp256k1::Message {
120    fn from(message: &Message) -> Self {
121        secp256k1::Message::from_digest_slice(&*message.0).expect("length always matches")
122    }
123}