@@ -17,7 +17,8 @@ use tw_memory::Data;
17
17
use crate :: encoder:: error:: Error ;
18
18
use crate :: encoder:: { Decodable , Encodable } ;
19
19
20
- const ADDRESS_HRP : & str = "pc" ;
20
+ use super :: network:: Network ;
21
+
21
22
const TREASURY_ADDRESS_STRING : & str = "000000000000000000000000000000000000000000" ;
22
23
23
24
/// Enum for Pactus address types.
@@ -66,18 +67,20 @@ impl Decodable for AddressType {
66
67
/// The hash is computed as RIPEMD160(Blake2b(public key)).
67
68
#[ derive( Debug , Clone , PartialEq ) ]
68
69
pub struct Address {
70
+ network : Network ,
69
71
addr_type : AddressType ,
70
72
pub_hash : H160 ,
71
73
}
72
74
73
75
impl Address {
74
- pub fn from_public_key ( public_key : & PublicKey ) -> Result < Self , AddressError > {
76
+ pub fn from_public_key ( public_key : & PublicKey , network : Network ) -> Result < Self , AddressError > {
75
77
let pud_data = public_key. to_bytes ( ) ;
76
78
let pub_hash_data =
77
79
ripemd_160 ( & blake2_b ( pud_data. as_ref ( ) , 32 ) . map_err ( |_| AddressError :: Internal ) ?) ;
78
80
let pub_hash = Address :: vec_to_pub_hash ( pub_hash_data) ?;
79
81
80
82
Ok ( Address {
83
+ network,
81
84
addr_type : AddressType :: Ed25519Account ,
82
85
pub_hash,
83
86
} )
@@ -110,12 +113,12 @@ impl fmt::Display for Address {
110
113
return f. write_str ( TREASURY_ADDRESS_STRING ) ;
111
114
}
112
115
116
+ let hrp = self . network . address_hrp ( ) . map_err ( |_| fmt:: Error ) ?;
113
117
let mut b32 = Vec :: with_capacity ( 33 ) ;
114
118
115
119
b32. push ( bech32:: u5:: try_from_u8 ( self . addr_type . clone ( ) as u8 ) . map_err ( |_| fmt:: Error ) ?) ;
116
120
b32. extend_from_slice ( & self . pub_hash . to_vec ( ) . to_base32 ( ) ) ;
117
- bech32:: encode_to_fmt ( f, ADDRESS_HRP , & b32, bech32:: Variant :: Bech32m )
118
- . map_err ( |_| fmt:: Error ) ?
121
+ bech32:: encode_to_fmt ( f, hrp, & b32, bech32:: Variant :: Bech32m ) . map_err ( |_| fmt:: Error ) ?
119
122
}
120
123
}
121
124
@@ -146,13 +149,15 @@ impl Decodable for Address {
146
149
let addr_type = AddressType :: decode ( r) ?;
147
150
if addr_type == AddressType :: Treasury {
148
151
return Ok ( Address {
152
+ network : Network :: Unknown ,
149
153
addr_type,
150
154
pub_hash : H160 :: new ( ) ,
151
155
} ) ;
152
156
}
153
157
154
158
let pub_hash = H160 :: decode ( r) ?;
155
159
Ok ( Address {
160
+ network : Network :: Unknown ,
156
161
addr_type,
157
162
pub_hash,
158
163
} )
@@ -165,16 +170,14 @@ impl FromStr for Address {
165
170
fn from_str ( s : & str ) -> Result < Self , AddressError > {
166
171
if s == TREASURY_ADDRESS_STRING {
167
172
return Ok ( Address {
173
+ network : Network :: Unknown ,
168
174
addr_type : AddressType :: Treasury ,
169
175
pub_hash : H160 :: new ( ) ,
170
176
} ) ;
171
177
}
172
178
173
179
let ( hrp, b32, _variant) = bech32:: decode ( s) . map_err ( |_| AddressError :: FromBech32Error ) ?;
174
-
175
- if hrp != ADDRESS_HRP {
176
- return Err ( AddressError :: InvalidHrp ) ;
177
- }
180
+ let network = Network :: try_from_hrp ( & hrp) ?;
178
181
179
182
if b32. len ( ) != 33 {
180
183
return Err ( AddressError :: InvalidInput ) ;
@@ -185,6 +188,7 @@ impl FromStr for Address {
185
188
let pub_hash = Address :: vec_to_pub_hash ( b8) ?;
186
189
187
190
Ok ( Address {
191
+ network,
188
192
addr_type,
189
193
pub_hash,
190
194
} )
@@ -241,12 +245,20 @@ mod test {
241
245
. decode_hex ( )
242
246
. unwrap ( ) ;
243
247
244
- let addr = deserialize :: < Address > ( & data) . unwrap ( ) ;
248
+ let mut addr = deserialize :: < Address > ( & data) . unwrap ( ) ;
245
249
assert ! ( !addr. is_treasury( ) ) ;
250
+
251
+ addr. network = Network :: Mainnet ;
246
252
assert_eq ! (
247
253
addr. to_string( ) ,
248
254
"pc1rqqqsyqcyq5rqwzqfpg9scrgwpuqqzqsr36kkra"
249
255
) ;
256
+
257
+ addr. network = Network :: Testnet ;
258
+ assert_eq ! (
259
+ addr. to_string( ) ,
260
+ "tpc1rqqqsyqcyq5rqwzqfpg9scrgwpuqqzqsrtuyllk"
261
+ ) ;
250
262
}
251
263
252
264
#[ test]
@@ -289,6 +301,7 @@ mod test {
289
301
for case in test_cases {
290
302
let pub_hash_data = case. pub_hash . decode_hex ( ) . unwrap ( ) ;
291
303
let addr = Address {
304
+ network : Network :: Mainnet ,
292
305
addr_type : case. addr_type ,
293
306
pub_hash : Address :: vec_to_pub_hash ( pub_hash_data) . unwrap ( ) ,
294
307
} ;
@@ -307,7 +320,7 @@ mod test {
307
320
"afeefca74d9a325cf1d6b6911d61a65c32afa8e02bd5e78e2e4ac2910bab45f5" ,
308
321
)
309
322
. unwrap ( ) ;
310
- let address = Address :: from_public_key ( & private_key. public ( ) ) . unwrap ( ) ;
323
+ let address = Address :: from_public_key ( & private_key. public ( ) , Network :: Mainnet ) . unwrap ( ) ;
311
324
let mut w = Vec :: new ( ) ;
312
325
313
326
address. encode ( & mut w) . unwrap ( ) ;
@@ -323,13 +336,16 @@ mod test {
323
336
. unwrap ( ) ;
324
337
let private_key = PrivateKey :: try_from ( private_key_data. as_slice ( ) ) . unwrap ( ) ;
325
338
let public_key = private_key. public ( ) ;
326
- let address = Address :: from_public_key ( & public_key) . unwrap ( ) ;
339
+ let mainnet_address = Address :: from_public_key ( & public_key, Network :: Mainnet ) . unwrap ( ) ;
340
+ let testnet_address = Address :: from_public_key ( & public_key, Network :: Testnet ) . unwrap ( ) ;
327
341
328
342
let expected_public_key =
329
343
"95794161374b22c696dabb98e93f6ca9300b22f3b904921fbf560bb72145f4fa" ;
330
- let expected_address = "pc1rwzvr8rstdqypr80ag3t6hqrtnss9nwymcxy3lr" ;
344
+ let expected_mainnet_address = "pc1rwzvr8rstdqypr80ag3t6hqrtnss9nwymcxy3lr" ;
345
+ let expected_testnet_address = "tpc1rwzvr8rstdqypr80ag3t6hqrtnss9nwymzqkcrg" ;
331
346
332
347
assert_eq ! ( public_key. to_bytes( ) . to_hex( ) , expected_public_key) ;
333
- assert_eq ! ( address. to_string( ) , expected_address) ;
348
+ assert_eq ! ( mainnet_address. to_string( ) , expected_mainnet_address) ;
349
+ assert_eq ! ( testnet_address. to_string( ) , expected_testnet_address) ;
334
350
}
335
351
}
0 commit comments