1use secp256k1::{Parity, PublicKey, 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 {
33 let node_addr = NodeAddr::from_pubkey(&pubkey);
34 let address = FipsAddress::from_node_addr(&node_addr);
35 let pubkey_full = pubkey.public_key(Parity::Even);
36 Self {
37 pubkey,
38 pubkey_full: Some(pubkey_full),
39 node_addr,
40 address,
41 }
42 }
43
44 pub fn from_pubkey_full(pubkey: PublicKey) -> Self {
49 let (x_only, _parity) = pubkey.x_only_public_key();
50 let node_addr = NodeAddr::from_pubkey(&x_only);
51 let address = FipsAddress::from_node_addr(&node_addr);
52 Self {
53 pubkey: x_only,
54 pubkey_full: Some(pubkey),
55 node_addr,
56 address,
57 }
58 }
59
60 pub fn from_npub(npub: &str) -> Result<Self, IdentityError> {
62 let pubkey = decode_npub(npub)?;
63 Ok(Self::from_pubkey(pubkey))
64 }
65
66 pub fn pubkey(&self) -> XOnlyPublicKey {
68 self.pubkey
69 }
70
71 pub fn pubkey_full(&self) -> PublicKey {
76 self.pubkey_full.unwrap_or_else(|| {
77 self.pubkey.public_key(Parity::Even)
79 })
80 }
81
82 pub fn npub(&self) -> String {
84 encode_npub(&self.pubkey)
85 }
86
87 pub fn short_npub(&self) -> String {
89 let full = self.npub();
90 let data = &full[5..]; format!("npub1{}...{}", &data[..4], &data[data.len() - 4..])
92 }
93
94 pub fn node_addr(&self) -> &NodeAddr {
96 &self.node_addr
97 }
98
99 pub fn address(&self) -> &FipsAddress {
101 &self.address
102 }
103
104 pub fn verify(&self, data: &[u8], signature: &secp256k1::schnorr::Signature) -> bool {
106 let digest = sha256(data);
107 super::SECP
108 .verify_schnorr(signature, &digest, &self.pubkey)
109 .is_ok()
110 }
111}
112
113impl fmt::Debug for PeerIdentity {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 f.debug_struct("PeerIdentity")
116 .field("node_addr", &self.node_addr)
117 .field("address", &self.address)
118 .finish()
119 }
120}
121
122impl fmt::Display for PeerIdentity {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 write!(f, "{}", self.npub())
125 }
126}