Skip to main content

defuse_core/payload/
tip191.rs

1use defuse_crypto::secp256k1::{Secp256k1RecoverableSignature, Secp256k1UncompressedPublicKey};
2use defuse_tip191::Tip191;
3use serde::{Deserialize, Serialize, de::DeserializeOwned};
4
5use crate::payload::{Payload, SignedPayload};
6
7use super::{DefusePayload, ExtractDefusePayload};
8
9#[cfg_attr(feature = "schemars-v0_8", derive(::schemars::JsonSchema))]
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct SignedTip191Payload {
12    pub payload: String,
13
14    /// There is no public key member because the public key can be recovered
15    /// via `ecrecover()` knowing the data and the signature
16    pub signature: Secp256k1RecoverableSignature,
17}
18
19impl Payload for SignedTip191Payload {
20    #[inline]
21    fn hash(&self) -> [u8; 32] {
22        Tip191::prehash(&self.payload)
23    }
24}
25
26impl SignedPayload for SignedTip191Payload {
27    type PublicKey = Secp256k1UncompressedPublicKey;
28
29    #[inline]
30    fn verify(&self) -> Option<Self::PublicKey> {
31        let (signature, recovery_id) = self.signature.try_into().ok()?;
32
33        Tip191::recover(&self.payload, &signature, recovery_id).map(Into::into)
34    }
35}
36
37impl<T> ExtractDefusePayload<T> for SignedTip191Payload
38where
39    T: DeserializeOwned,
40{
41    type Error = serde_json::Error;
42
43    #[inline]
44    fn extract_defuse_payload(self) -> Result<DefusePayload<T>, Self::Error> {
45        serde_json::from_str(&self.payload)
46    }
47}