notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

pubkey.rs (4110B)


      1 use serde::{Deserialize, Deserializer, Serialize, Serializer};
      2 
      3 use crate::Error;
      4 use std::borrow::Borrow;
      5 use std::fmt;
      6 use std::ops::Deref;
      7 use tracing::debug;
      8 
      9 #[derive(Eq, PartialEq, Clone, Copy, Hash, Ord, PartialOrd)]
     10 pub struct Pubkey([u8; 32]);
     11 
     12 #[derive(Eq, PartialEq, Clone, Copy, Hash, Ord, PartialOrd)]
     13 pub struct PubkeyRef<'a>(&'a [u8; 32]);
     14 
     15 static HRP_NPUB: bech32::Hrp = bech32::Hrp::parse_unchecked("npub");
     16 
     17 impl Borrow<[u8; 32]> for PubkeyRef<'_> {
     18     fn borrow(&self) -> &[u8; 32] {
     19         self.0
     20     }
     21 }
     22 
     23 impl<'a> PubkeyRef<'a> {
     24     pub fn new(bytes: &'a [u8; 32]) -> Self {
     25         Self(bytes)
     26     }
     27 
     28     pub fn bytes(&self) -> &[u8; 32] {
     29         self.0
     30     }
     31 
     32     pub fn to_owned(&self) -> Pubkey {
     33         Pubkey::new(*self.bytes())
     34     }
     35 
     36     pub fn hex(&self) -> String {
     37         hex::encode(self.bytes())
     38     }
     39 }
     40 
     41 impl Deref for Pubkey {
     42     type Target = [u8; 32];
     43 
     44     fn deref(&self) -> &Self::Target {
     45         &self.0
     46     }
     47 }
     48 
     49 impl Borrow<[u8; 32]> for Pubkey {
     50     fn borrow(&self) -> &[u8; 32] {
     51         &self.0
     52     }
     53 }
     54 
     55 impl Pubkey {
     56     pub fn new(data: [u8; 32]) -> Self {
     57         Self(data)
     58     }
     59 
     60     pub fn hex(&self) -> String {
     61         hex::encode(self.bytes())
     62     }
     63 
     64     pub fn bytes(&self) -> &[u8; 32] {
     65         &self.0
     66     }
     67 
     68     pub fn as_ref(&self) -> PubkeyRef<'_> {
     69         PubkeyRef(self.bytes())
     70     }
     71 
     72     pub fn parse(s: &str) -> Result<Self, Error> {
     73         match Pubkey::from_hex(s) {
     74             Ok(pk) => Ok(pk),
     75             Err(_) => Pubkey::try_from_bech32_string(s, false),
     76         }
     77     }
     78 
     79     pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
     80         Ok(Pubkey(hex::decode(hex_str)?.as_slice().try_into()?))
     81     }
     82 
     83     pub fn try_from_hex_str_with_verify(hex_str: &str) -> Result<Self, Error> {
     84         let vec: Vec<u8> = hex::decode(hex_str)?;
     85         if vec.len() != 32 {
     86             Err(Error::HexDecodeFailed)
     87         } else {
     88             let _ = match nostr::secp256k1::XOnlyPublicKey::from_slice(&vec) {
     89                 Ok(r) => Ok(r),
     90                 Err(_) => Err(Error::InvalidPublicKey),
     91             }?;
     92 
     93             Ok(Pubkey(vec.try_into().unwrap()))
     94         }
     95     }
     96 
     97     pub fn try_from_bech32_string(s: &str, verify: bool) -> Result<Self, Error> {
     98         let data = match bech32::decode(s) {
     99             Ok(res) => Ok(res),
    100             Err(_) => Err(Error::InvalidBech32),
    101         }?;
    102 
    103         if data.0 != HRP_NPUB {
    104             Err(Error::InvalidBech32)
    105         } else if data.1.len() != 32 {
    106             Err(Error::InvalidByteSize)
    107         } else {
    108             if verify {
    109                 let _ = match nostr::secp256k1::XOnlyPublicKey::from_slice(&data.1) {
    110                     Ok(r) => Ok(r),
    111                     Err(_) => Err(Error::InvalidPublicKey),
    112                 }?;
    113             }
    114             Ok(Pubkey(data.1.try_into().unwrap()))
    115         }
    116     }
    117 
    118     pub fn to_bech(&self) -> Option<String> {
    119         bech32::encode::<bech32::Bech32>(HRP_NPUB, &self.0).ok()
    120     }
    121 }
    122 
    123 impl fmt::Display for Pubkey {
    124     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    125         write!(f, "{}", self.hex())
    126     }
    127 }
    128 
    129 impl fmt::Debug for PubkeyRef<'_> {
    130     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    131         write!(f, "{}", self.hex())
    132     }
    133 }
    134 
    135 impl fmt::Debug for Pubkey {
    136     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    137         write!(f, "{}", self.hex())
    138     }
    139 }
    140 
    141 impl From<Pubkey> for String {
    142     fn from(pk: Pubkey) -> Self {
    143         pk.hex()
    144     }
    145 }
    146 
    147 // Custom serialize function for Pubkey
    148 impl Serialize for Pubkey {
    149     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    150     where
    151         S: Serializer,
    152     {
    153         serializer.serialize_str(&self.hex())
    154     }
    155 }
    156 
    157 // Custom deserialize function for Pubkey
    158 impl<'de> Deserialize<'de> for Pubkey {
    159     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    160     where
    161         D: Deserializer<'de>,
    162     {
    163         debug!("decoding pubkey start");
    164         let s = String::deserialize(deserializer)?;
    165         debug!("decoding pubkey {}", &s);
    166         Pubkey::from_hex(&s).map_err(serde::de::Error::custom)
    167     }
    168 }