1use secp256k1::{Parity, PublicKey, Secp256k1, XOnlyPublicKey};
4use std::fmt;
5
6use super::encoding::{decode_npub, encode_npub};
7use super::{FipsAddress, IdentityError, NodeAddr, sha256};
8
9#[derive(Clone, Copy, PartialEq, Eq)]
14pub struct PeerIdentity {
15 pubkey: XOnlyPublicKey,
16 pubkey_full: Option<PublicKey>,
18 node_addr: NodeAddr,
19 address: FipsAddress,
20}
21
22impl PeerIdentity {
23 pub fn from_pubkey(pubkey: XOnlyPublicKey) -> Self {
34 let node_addr = NodeAddr::from_pubkey(&pubkey);
35 let address = FipsAddress::from_node_addr(&node_addr);
36 let pubkey_full = pubkey.public_key(Parity::Even);
37 Self {
38 pubkey,
39 pubkey_full: Some(pubkey_full),
40 node_addr,
41 address,
42 }
43 }
44
45 pub fn from_pubkey_full(pubkey: PublicKey) -> Self {
50 let (x_only, _parity) = pubkey.x_only_public_key();
51 let node_addr = NodeAddr::from_pubkey(&x_only);
52 let address = FipsAddress::from_node_addr(&node_addr);
53 Self {
54 pubkey: x_only,
55 pubkey_full: Some(pubkey),
56 node_addr,
57 address,
58 }
59 }
60
61 pub fn from_npub(npub: &str) -> Result<Self, IdentityError> {
63 let pubkey = decode_npub(npub)?;
64 Ok(Self::from_pubkey(pubkey))
65 }
66
67 pub fn pubkey(&self) -> XOnlyPublicKey {
69 self.pubkey
70 }
71
72 pub fn pubkey_full(&self) -> PublicKey {
77 self.pubkey_full.unwrap_or_else(|| {
78 self.pubkey.public_key(Parity::Even)
80 })
81 }
82
83 pub fn npub(&self) -> String {
85 encode_npub(&self.pubkey)
86 }
87
88 pub fn short_npub(&self) -> String {
90 let full = self.npub();
91 let data = &full[5..]; format!("npub1{}...{}", &data[..4], &data[data.len() - 4..])
93 }
94
95 pub fn node_addr(&self) -> &NodeAddr {
97 &self.node_addr
98 }
99
100 pub fn address(&self) -> &FipsAddress {
102 &self.address
103 }
104
105 pub fn verify(&self, data: &[u8], signature: &secp256k1::schnorr::Signature) -> bool {
107 let secp = Secp256k1::new();
108 let digest = sha256(data);
109 secp.verify_schnorr(signature, &digest, &self.pubkey)
110 .is_ok()
111 }
112}
113
114impl fmt::Debug for PeerIdentity {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 f.debug_struct("PeerIdentity")
117 .field("node_addr", &self.node_addr)
118 .field("address", &self.address)
119 .finish()
120 }
121}
122
123impl fmt::Display for PeerIdentity {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 write!(f, "{}", self.npub())
126 }
127}