tezos_smart_rollup_encoding/
public_key_hash.rs1use std::fmt::Display;
8use tezos_data_encoding::enc::BinWriter;
9use tezos_data_encoding::encoding::HasEncoding;
10use tezos_data_encoding::nom::NomReader;
11
12use crypto::base58::{FromBase58Check, FromBase58CheckError};
13use crypto::hash::{
14 ContractTz1Hash, ContractTz2Hash, ContractTz3Hash, Hash, HashTrait, HashType,
15};
16
17#[derive(
19 Debug, Clone, PartialEq, Eq, PartialOrd, Ord, HasEncoding, BinWriter, NomReader,
20)]
21pub enum PublicKeyHash {
22 Ed25519(ContractTz1Hash),
24 Secp256k1(ContractTz2Hash),
26 P256(ContractTz3Hash),
28}
29
30impl Display for PublicKeyHash {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 match self {
33 Self::Ed25519(tz1) => write!(f, "{}", tz1),
34 Self::Secp256k1(tz2) => write!(f, "{}", tz2),
35 Self::P256(tz3) => write!(f, "{}", tz3),
36 }
37 }
38}
39
40impl PublicKeyHash {
41 pub fn from_b58check(data: &str) -> Result<Self, FromBase58CheckError> {
43 let bytes = data.from_base58check()?;
44 match bytes {
45 _ if bytes.starts_with(HashType::ContractTz1Hash.base58check_prefix()) => Ok(
46 PublicKeyHash::Ed25519(ContractTz1Hash::from_b58check(data)?),
47 ),
48 _ if bytes.starts_with(HashType::ContractTz2Hash.base58check_prefix()) => Ok(
49 PublicKeyHash::Secp256k1(ContractTz2Hash::from_b58check(data)?),
50 ),
51 _ if bytes.starts_with(HashType::ContractTz3Hash.base58check_prefix()) => {
52 Ok(PublicKeyHash::P256(ContractTz3Hash::from_b58check(data)?))
53 }
54 _ => Err(FromBase58CheckError::InvalidBase58),
55 }
56 }
57
58 pub fn to_b58check(&self) -> String {
60 match self {
61 Self::Ed25519(tz1) => tz1.to_b58check(),
62 Self::Secp256k1(tz2) => tz2.to_b58check(),
63 Self::P256(tz3) => tz3.to_b58check(),
64 }
65 }
66}
67
68impl From<PublicKeyHash> for Hash {
69 fn from(pkh: PublicKeyHash) -> Self {
70 match pkh {
71 PublicKeyHash::Ed25519(tz1) => tz1.into(),
72 PublicKeyHash::Secp256k1(tz2) => tz2.into(),
73 PublicKeyHash::P256(tz3) => tz3.into(),
74 }
75 }
76}
77
78impl TryFrom<&str> for PublicKeyHash {
79 type Error = FromBase58CheckError;
80
81 fn try_from(value: &str) -> Result<Self, Self::Error> {
82 Self::from_b58check(value)
83 }
84}
85
86#[cfg(test)]
87mod test {
88 use super::*;
89
90 #[test]
91 fn tz1_b58check() {
92 let tz1 = "tz1RjtZUVeLhADFHDL8UwDZA6vjWWhojpu5w";
93
94 let pkh = PublicKeyHash::from_b58check(tz1);
95
96 assert!(matches!(pkh, Ok(PublicKeyHash::Ed25519(_))));
97
98 let tz1_from_pkh = pkh.unwrap().to_b58check();
99
100 assert_eq!(tz1, &tz1_from_pkh);
101 }
102
103 #[test]
104 fn tz2_b58check() {
105 let tz2 = "tz2VGBaXuS6rnaa5hpC92qkgadRJKdEbeGwc";
106
107 let pkh = PublicKeyHash::from_b58check(tz2);
108
109 assert!(matches!(pkh, Ok(PublicKeyHash::Secp256k1(_))));
110
111 let tz2_from_pkh = pkh.unwrap().to_b58check();
112
113 assert_eq!(tz2, &tz2_from_pkh);
114 }
115
116 #[test]
117 fn tz3_b58check() {
118 let tz3 = "tz3WEJYwJ6pPwVbSL8FrSoAXRmFHHZTuEnMA";
119
120 let pkh = PublicKeyHash::from_b58check(tz3);
121
122 assert!(matches!(pkh, Ok(PublicKeyHash::P256(_))));
123
124 let tz3_from_pkh = pkh.unwrap().to_b58check();
125
126 assert_eq!(tz3, &tz3_from_pkh);
127 }
128
129 #[test]
130 fn tz1_encoding() {
131 let tz1 = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx";
132
133 let pkh = PublicKeyHash::from_b58check(tz1).expect("expected valid tz1 hash");
134
135 let mut bin = Vec::new();
136 pkh.bin_write(&mut bin).expect("serialization should work");
137
138 let deserde_pkh = NomReader::nom_read(bin.as_slice())
139 .expect("deserialization should work")
140 .1;
141
142 assert_eq!(0_u8, bin[0]);
144 assert_eq!(pkh, deserde_pkh);
145 }
146
147 #[test]
148 fn tz2_encoding() {
149 let tz2 = "tz2KZPgf2rshxNUBXFcTaCemik1LH1v9qz3F";
150
151 let pkh = PublicKeyHash::from_b58check(tz2).expect("expected valid tz2 hash");
152
153 let mut bin = Vec::new();
154 pkh.bin_write(&mut bin).expect("serialization should work");
155
156 let deserde_pkh = NomReader::nom_read(bin.as_slice())
157 .expect("deserialization should work")
158 .1;
159
160 assert_eq!(1_u8, bin[0]);
162 assert_eq!(pkh, deserde_pkh);
163 }
164
165 #[test]
166 fn tz3_encoding() {
167 let tz3 = "tz3fTJbAxj1LQCEKDKmYLWKP6e5vNC9vwvyo";
168
169 let pkh = PublicKeyHash::from_b58check(tz3).expect("expected valid tz3 hash");
170
171 let mut bin = Vec::new();
172 pkh.bin_write(&mut bin).expect("serialization should work");
173
174 let deserde_pkh = NomReader::nom_read(bin.as_slice())
175 .expect("deserialization should work")
176 .1;
177
178 assert_eq!(2_u8, bin[0]);
180 assert_eq!(pkh, deserde_pkh);
181 }
182}