stellar_base/crypto/
public_key.rs

1use std::convert::TryInto;
2
3use crate::crypto::strkey;
4use crate::error::{Error, Result};
5use crate::xdr;
6
7/// The public key of the account.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct PublicKey(pub [u8; 32]);
10
11impl PublicKey {
12    /// Create from `account_id`, e.g. `GB3KJPLFUYN5VL6R3GU3EGCGVCKFDSD7BEDX42HWG5BWFKB3KQGJJRMA`.
13    pub fn from_account_id(account_id: &str) -> Result<PublicKey> {
14        let bytes = strkey::decode_account_id(account_id)?;
15        Self::from_slice(&bytes)
16    }
17
18    /// Create from raw bytes.
19    pub fn from_slice(data: &[u8]) -> Result<PublicKey> {
20        // let key = ed25519::PublicKey::from_slice(&data).ok_or(Error::InvalidPublicKey)?;
21        Ok(PublicKey(
22            data.try_into().map_err(|_| Error::InvalidPublicKey)?,
23        ))
24    }
25
26    pub fn account_id(&self) -> String {
27        strkey::encode_account_id(&self.0)
28    }
29
30    pub fn into_muxed_account(self, id: u64) -> MuxedAccount {
31        let inner = MuxedEd25519PublicKey { key: self, id };
32        MuxedAccount::MuxedEd25519(inner)
33    }
34
35    pub fn to_muxed_account(&self, id: u64) -> MuxedAccount {
36        (*self).into_muxed_account(id)
37    }
38
39    pub fn to_xdr_uint256(&self) -> Result<xdr::Uint256> {
40        Ok(xdr::Uint256(self.0))
41    }
42
43    pub fn to_xdr_public_key(&self) -> Result<xdr::PublicKey> {
44        let uint256 = self.to_xdr_uint256()?;
45        Ok(xdr::PublicKey::PublicKeyTypeEd25519(uint256))
46    }
47
48    pub fn to_xdr_account_id(&self) -> Result<xdr::AccountId> {
49        let public_key = self.to_xdr_public_key()?;
50        Ok(xdr::AccountId(public_key))
51    }
52
53    pub fn from_xdr_public_key(x: &xdr::PublicKey) -> Result<PublicKey> {
54        match x {
55            xdr::PublicKey::PublicKeyTypeEd25519(inner) => Self::from_slice(&inner.0),
56        }
57    }
58
59    pub fn from_xdr_account_id(x: &xdr::AccountId) -> Result<PublicKey> {
60        Self::from_xdr_public_key(&x.0)
61    }
62
63    pub fn as_bytes(&self) -> &[u8] {
64        &self.0
65    }
66
67    pub fn to_xdr(&self) -> Result<xdr::MuxedAccount> {
68        let uint256 = self.to_xdr_uint256()?;
69        Ok(xdr::MuxedAccount::Ed25519(uint256))
70    }
71}
72
73/// A public key together with an id.
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct MuxedEd25519PublicKey {
76    key: PublicKey,
77    id: u64,
78}
79
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub enum MuxedAccount {
82    Ed25519(PublicKey),
83    MuxedEd25519(MuxedEd25519PublicKey),
84}
85
86impl MuxedEd25519PublicKey {
87    pub fn new(key: PublicKey, id: u64) -> MuxedEd25519PublicKey {
88        MuxedEd25519PublicKey { key, id }
89    }
90
91    pub fn from_account_id(account_id: &str) -> Result<MuxedEd25519PublicKey> {
92        let (bytes, id) = strkey::decode_muxed_account(account_id)?;
93        Self::from_slice(&bytes, id)
94    }
95
96    /// Create from raw byte and id.
97    pub fn from_slice(data: &[u8], id: u64) -> Result<MuxedEd25519PublicKey> {
98        let key = PublicKey::from_slice(data)?;
99        Ok(MuxedEd25519PublicKey { key, id })
100    }
101
102    /// Return the inner key.
103    pub fn public_key(&self) -> &PublicKey {
104        &self.key
105    }
106
107    pub fn account_id(&self) -> String {
108        strkey::encode_muxed_account(self.key.as_bytes(), self.id)
109    }
110
111    pub fn to_xdr(&self) -> Result<xdr::MuxedAccount> {
112        let uint256 = self.key.to_xdr_uint256()?;
113        let muxed = xdr::MuxedAccountMed25519 {
114            id: self.id,
115            ed25519: uint256,
116        };
117        Ok(xdr::MuxedAccount::MuxedEd25519(muxed))
118    }
119}
120
121impl MuxedAccount {
122    pub fn account_id(&self) -> String {
123        match self {
124            MuxedAccount::Ed25519(pk) => pk.account_id(),
125            MuxedAccount::MuxedEd25519(mx) => mx.account_id(),
126        }
127    }
128
129    pub fn to_xdr(&self) -> Result<xdr::MuxedAccount> {
130        match self {
131            MuxedAccount::Ed25519(pk) => pk.to_xdr(),
132            MuxedAccount::MuxedEd25519(mx) => mx.to_xdr(),
133        }
134    }
135
136    pub fn from_xdr(x: &xdr::MuxedAccount) -> Result<MuxedAccount> {
137        match x {
138            xdr::MuxedAccount::Ed25519(buf) => {
139                let inner = PublicKey::from_slice(&buf.0)?;
140                Ok(MuxedAccount::Ed25519(inner))
141            }
142            xdr::MuxedAccount::MuxedEd25519(mx) => {
143                let inner = MuxedEd25519PublicKey::from_slice(&mx.ed25519.0, mx.id)?;
144                Ok(MuxedAccount::MuxedEd25519(inner))
145            }
146        }
147    }
148}
149
150impl From<PublicKey> for MuxedAccount {
151    fn from(pk: PublicKey) -> Self {
152        MuxedAccount::Ed25519(pk)
153    }
154}
155
156impl From<MuxedEd25519PublicKey> for MuxedAccount {
157    fn from(muxed: MuxedEd25519PublicKey) -> Self {
158        MuxedAccount::MuxedEd25519(muxed)
159    }
160}
161
162impl std::str::FromStr for PublicKey {
163    type Err = crate::error::Error;
164
165    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
166        let pk = PublicKey::from_account_id(s)?;
167        Ok(pk)
168    }
169}
170
171impl std::fmt::Display for PublicKey {
172    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
173        write!(f, "{}", self.account_id())
174    }
175}