1use std::fmt::{self, Display, Formatter};
51use std::str::FromStr;
52
53use bitcoin_bech32::{self, WitnessProgram, u5};
54use bitcoin_hashes::{hash160, Hash};
55use secp256k1::key::PublicKey;
56
57#[cfg(feature = "serde")]
58use serde;
59
60use blockdata::opcodes;
61use blockdata::script;
62use network::constants::Network;
63use consensus::encode;
64use util::base58;
65
66#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
68pub enum Payload {
69 Pubkey(PublicKey),
71 PubkeyHash(hash160::Hash),
73 ScriptHash(hash160::Hash),
75 WitnessProgram(WitnessProgram),
77}
78
79#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
80pub struct Address {
82 pub payload: Payload,
84 pub network: Network
86}
87
88impl Address {
89 #[inline]
92 pub fn p2pkh(pk: &PublicKey, network: Network) -> Address {
93 Address {
94 network: network,
95 payload: Payload::PubkeyHash(hash160::Hash::hash(&pk.serialize()[..]))
96 }
97 }
98
99 #[inline]
103 pub fn p2upkh(pk: &PublicKey, network: Network) -> Address {
104 Address {
105 network: network,
106 payload: Payload::PubkeyHash(hash160::Hash::hash(&pk.serialize_uncompressed()[..]))
107 }
108 }
109
110 #[inline]
114 pub fn p2pk(pk: &PublicKey, network: Network) -> Address {
115 Address {
116 network: network,
117 payload: Payload::Pubkey(*pk)
118 }
119 }
120
121 #[inline]
124 pub fn p2sh(script: &script::Script, network: Network) -> Address {
125 Address {
126 network: network,
127 payload: Payload::ScriptHash(hash160::Hash::hash(&script[..]))
128 }
129 }
130
131 pub fn p2wpkh (pk: &PublicKey, network: Network) -> Address {
134 Address {
135 network: network,
136 payload: Payload::WitnessProgram(
137 WitnessProgram::new(u5::try_from_u8(0).expect("0<32"),
139 hash160::Hash::hash(&pk.serialize()[..])[..].to_vec(),
140 Address::bech_network(network)).unwrap())
141 }
142 }
143
144 pub fn p2shwpkh (pk: &PublicKey, network: Network) -> Address {
147 let builder = script::Builder::new()
148 .push_int(0)
149 .push_slice(&hash160::Hash::hash(&pk.serialize()[..])[..]);
150 Address {
151 network: network,
152 payload: Payload::ScriptHash(
153 hash160::Hash::hash(builder.into_script().as_bytes())
154 )
155 }
156 }
157
158 pub fn p2wsh (script: &script::Script, network: Network) -> Address {
160 use bitcoin_hashes::sha256;
161 use bitcoin_hashes::Hash;
162
163 Address {
164 network: network,
165 payload: Payload::WitnessProgram(
166 WitnessProgram::new(
168 u5::try_from_u8(0).expect("0<32"),
169 sha256::Hash::hash(&script[..])[..].to_vec(),
170 Address::bech_network(network)
171 ).unwrap()
172 )
173 }
174 }
175
176 pub fn p2shwsh (script: &script::Script, network: Network) -> Address {
179 use bitcoin_hashes::sha256;
180 use bitcoin_hashes::Hash;
181 use bitcoin_hashes::hash160;
182
183 let ws = script::Builder::new().push_int(0)
184 .push_slice(&sha256::Hash::hash(&script[..])[..])
185 .into_script();
186
187 Address {
188 network: network,
189 payload: Payload::ScriptHash(hash160::Hash::hash(&ws[..]))
190 }
191 }
192
193 #[inline]
194 fn bech_network (network: Network) -> bitcoin_bech32::constants::Network {
196 match network {
197 Network::Bitcoin => bitcoin_bech32::constants::Network::Bitcoin,
198 Network::Testnet => bitcoin_bech32::constants::Network::Testnet,
199 Network::Regtest => bitcoin_bech32::constants::Network::Regtest,
200 }
201 }
202
203 pub fn script_pubkey(&self) -> script::Script {
205 match self.payload {
206 Payload::Pubkey(ref pk) => {
207 script::Builder::new()
208 .push_slice(&pk.serialize_uncompressed()[..])
209 .push_opcode(opcodes::all::OP_CHECKSIG)
210 },
211 Payload::PubkeyHash(ref hash) => {
212 script::Builder::new()
213 .push_opcode(opcodes::all::OP_DUP)
214 .push_opcode(opcodes::all::OP_HASH160)
215 .push_slice(&hash[..])
216 .push_opcode(opcodes::all::OP_EQUALVERIFY)
217 .push_opcode(opcodes::all::OP_CHECKSIG)
218 },
219 Payload::ScriptHash(ref hash) => {
220 script::Builder::new()
221 .push_opcode(opcodes::all::OP_HASH160)
222 .push_slice(&hash[..])
223 .push_opcode(opcodes::all::OP_EQUAL)
224 },
225 Payload::WitnessProgram(ref witprog) => {
226 script::Builder::new()
227 .push_int(witprog.version().to_u8() as i64)
228 .push_slice(witprog.program())
229 }
230 }.into_script()
231 }
232}
233
234impl Display for Address {
235 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
236 match self.payload {
237 Payload::Pubkey(ref pk) => {
239 let hash = &hash160::Hash::hash(&pk.serialize_uncompressed()[..]);
240 let mut prefixed = [0; 21];
241 prefixed[0] = match self.network {
242 Network::Bitcoin => 0,
243 Network::Testnet | Network::Regtest => 111,
244 };
245 prefixed[1..].copy_from_slice(&hash[..]);
246 base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
247 },
248 Payload::PubkeyHash(ref hash) => {
249 let mut prefixed = [0; 21];
250 prefixed[0] = match self.network {
251 Network::Bitcoin => 0,
252 Network::Testnet | Network::Regtest => 111,
253 };
254 prefixed[1..].copy_from_slice(&hash[..]);
255 base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
256 },
257 Payload::ScriptHash(ref hash) => {
258 let mut prefixed = [0; 21];
259 prefixed[0] = match self.network {
260 Network::Bitcoin => 5,
261 Network::Testnet | Network::Regtest => 196,
262 };
263 prefixed[1..].copy_from_slice(&hash[..]);
264 base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
265 },
266 Payload::WitnessProgram(ref witprog) => {
267 fmt.write_str(&witprog.to_address())
268 },
269 }
270 }
271}
272
273impl FromStr for Address {
274 type Err = encode::Error;
275
276 fn from_str(s: &str) -> Result<Address, encode::Error> {
277 if s.starts_with("bc1") || s.starts_with("BC1") ||
279 s.starts_with("tb1") || s.starts_with("TB1") ||
280 s.starts_with("bcrt1") || s.starts_with("BCRT1")
281 {
282 let witprog = WitnessProgram::from_address(s)?;
283 let network = match witprog.network() {
284 bitcoin_bech32::constants::Network::Bitcoin => Network::Bitcoin,
285 bitcoin_bech32::constants::Network::Testnet => Network::Testnet,
286 bitcoin_bech32::constants::Network::Regtest => Network::Regtest,
287 _ => panic!("unknown network")
288 };
289 if witprog.version().to_u8() != 0 {
290 return Err(encode::Error::UnsupportedWitnessVersion(witprog.version().to_u8()));
291 }
292 return Ok(Address {
293 network: network,
294 payload: Payload::WitnessProgram(witprog)
295 });
296 }
297
298 if s.len() > 50 {
299 return Err(encode::Error::Base58(base58::Error::InvalidLength(s.len() * 11 / 15)));
300 }
301
302 let data = base58::from_check(s)?;
304
305 if data.len() != 21 {
306 return Err(encode::Error::Base58(base58::Error::InvalidLength(data.len())));
307 }
308
309 let (network, payload) = match data[0] {
310 0 => (
311 Network::Bitcoin,
312 Payload::PubkeyHash(hash160::Hash::from_slice(&data[1..]).unwrap())
313 ),
314 5 => (
315 Network::Bitcoin,
316 Payload::ScriptHash(hash160::Hash::from_slice(&data[1..]).unwrap())
317 ),
318 111 => (
319 Network::Testnet,
320 Payload::PubkeyHash(hash160::Hash::from_slice(&data[1..]).unwrap())
321 ),
322 196 => (
323 Network::Testnet,
324 Payload::ScriptHash(hash160::Hash::from_slice(&data[1..]).unwrap())
325 ),
326 x => return Err(encode::Error::Base58(base58::Error::InvalidVersion(vec![x])))
327 };
328
329 Ok(Address {
330 network: network,
331 payload: payload,
332 })
333 }
334}
335
336impl ::std::fmt::Debug for Address {
337 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
338 write!(f, "{}", self.to_string())
339 }
340}
341
342#[cfg(feature = "serde")]
343impl<'de> serde::Deserialize<'de> for Address {
344 #[inline]
345 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
346 where
347 D: serde::Deserializer<'de>,
348 {
349 use std::fmt::{self, Formatter};
350
351 struct Visitor;
352 impl<'de> serde::de::Visitor<'de> for Visitor {
353 type Value = Address;
354
355 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
356 formatter.write_str("a Bitcoin address")
357 }
358
359 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
360 where
361 E: serde::de::Error,
362 {
363 Address::from_str(v).map_err(E::custom)
364 }
365
366 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
367 where
368 E: serde::de::Error,
369 {
370 self.visit_str(v)
371 }
372
373 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
374 where
375 E: serde::de::Error,
376 {
377 self.visit_str(&v)
378 }
379 }
380
381 deserializer.deserialize_str(Visitor)
382 }
383}
384
385#[cfg(feature = "serde")]
386impl serde::Serialize for Address {
387 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
388 where
389 S: serde::Serializer,
390 {
391 serializer.serialize_str(&self.to_string())
392 }
393}
394
395#[cfg(test)]
396mod tests {
397 use std::str::FromStr;
398 use std::string::ToString;
399
400 use bitcoin_hashes::{hash160, Hash};
401 use secp256k1::key::PublicKey;
402 use hex::decode as hex_decode;
403
404 use blockdata::script::Script;
405 use network::constants::Network::{Bitcoin, Testnet, Regtest};
406 use super::*;
407
408 macro_rules! hex (($hex:expr) => (hex_decode($hex).unwrap()));
409 macro_rules! hex_key (($hex:expr) => (PublicKey::from_slice(&hex!($hex)).unwrap()));
410 macro_rules! hex_script (($hex:expr) => (Script::from(hex!($hex))));
411 macro_rules! hex_hash160 (($hex:expr) => (hash160::Hash::from_slice(&hex!($hex)).unwrap()));
412
413 #[test]
414 fn test_p2pkh_address_58() {
415 let addr = Address {
416 network: Bitcoin,
417 payload: Payload::PubkeyHash(
418 hex_hash160!("162c5ea71c0b23f5b9022ef047c4a86470a5b070")
419 )
420 };
421
422 assert_eq!(addr.script_pubkey(), hex_script!("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac"));
423 assert_eq!(&addr.to_string(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM");
424 assert_eq!(Address::from_str("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM").unwrap(), addr);
425 }
426
427 #[test]
428 fn test_p2pkh_from_key() {
429 let key = hex_key!("048d5141948c1702e8c95f438815794b87f706a8d4cd2bffad1dc1570971032c9b6042a0431ded2478b5c9cf2d81c124a5e57347a3c63ef0e7716cf54d613ba183");
430 let addr = Address::p2upkh(&key, Bitcoin);
431 assert_eq!(&addr.to_string(), "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY");
432
433 let key = hex_key!(&"03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f");
434 let addr = Address::p2pkh(&key, Testnet);
435 assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC");
436 }
437
438 #[test]
439 fn test_p2pk () {
440 let key = hex_key!("047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77");
442 let addr = Address::p2pk(&key, Bitcoin);
443 assert_eq!(&addr.to_string(), "1HLoD9E4SDFFPDiYfNYnkBLQ85Y51J3Zb1");
444 }
445
446 #[test]
447 fn test_p2sh_address_58() {
448 let addr = Address {
449 network: Bitcoin,
450 payload: Payload::ScriptHash(
451 hex_hash160!("162c5ea71c0b23f5b9022ef047c4a86470a5b070")
452 )
453 };
454
455 assert_eq!(addr.script_pubkey(), hex_script!("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087"));
456 assert_eq!(&addr.to_string(), "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k");
457 assert_eq!(Address::from_str("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k").unwrap(), addr);
458 }
459
460 #[test]
461 fn test_p2sh_parse() {
462 let script = hex_script!("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae");
463 let addr = Address::p2sh(&script, Testnet);
464
465 assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr");
466 assert_eq!(Address::from_str("2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr").unwrap(), addr);
467 }
468
469 #[test]
470 fn test_p2wpkh () {
471 let key = hex_key!("033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc");
473 let addr = Address::p2wpkh(&key, Bitcoin);
474 assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw");
475 }
476
477
478 #[test]
479 fn test_p2wsh () {
480 let script = hex_script!("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae");
482 let addr = Address::p2wsh(&script, Bitcoin);
483 assert_eq!(&addr.to_string(), "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej");
484 }
485
486
487 #[test]
488 fn test_bip173_vectors() {
489 let addrstr = "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4";
490 let addr = Address::from_str(addrstr).unwrap();
491 assert_eq!(addr.network, Bitcoin);
492 assert_eq!(addr.script_pubkey(), hex_script!("0014751e76e8199196d454941c45d1b3a323f1433bd6"));
493 let addrstr = "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7";
496 let addr = Address::from_str(addrstr).unwrap();
497 assert_eq!(addr.network, Testnet);
498 assert_eq!(addr.script_pubkey(), hex_script!("00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"));
499 assert_eq!(addr.to_string(), addrstr);
500
501 let addrstr = "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy";
502 let addr = Address::from_str(addrstr).unwrap();
503 assert_eq!(addr.network, Testnet);
504 assert_eq!(addr.script_pubkey(), hex_script!("0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433"));
505 assert_eq!(addr.to_string(), addrstr);
506
507 let addrstr = "bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl";
508 let addr = Address::from_str(addrstr).unwrap();
509 assert_eq!(addr.network, Regtest);
510 assert_eq!(addr.script_pubkey(), hex_script!("001454d26dddb59c7073c6a197946ea1841951fa7a74"));
511 assert_eq!(addr.to_string(), addrstr);
512
513 let addrstr = "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty"; assert!(Address::from_str(addrstr).is_err());
516
517 let addrstr = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5"; assert!(Address::from_str(addrstr).is_err());
519
520 let addrstr = "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2"; assert!(Address::from_str(addrstr).is_err());
522
523 let addrstr = "bc1rw5uspcuh"; assert!(Address::from_str(addrstr).is_err());
525
526 let addrstr = "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90"; assert!(Address::from_str(addrstr).is_err());
528
529 let addrstr = "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P"; assert!(Address::from_str(addrstr).is_err());
531
532 let addrstr = "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7"; assert!(Address::from_str(addrstr).is_err());
534
535 let addrstr = "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du"; assert!(Address::from_str(addrstr).is_err());
537
538 let addrstr = "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv"; assert!(Address::from_str(addrstr).is_err());
540
541 let addrstr = "bc1gmk9yu"; assert!(Address::from_str(addrstr).is_err());
543 }
544
545 #[test]
546 #[cfg(all(feature = "serde", feature = "strason"))]
547 fn test_json_serialize() {
548 use strason::Json;
549
550 let addr = Address::from_str("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM").unwrap();
551 let json = Json::from_serialize(&addr).unwrap();
552 assert_eq!(json.string(), Some("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"));
553 let into: Address = json.into_deserialize().unwrap();
554 assert_eq!(addr.to_string(), into.to_string());
555 assert_eq!(
556 into.script_pubkey(),
557 hex_script!("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac")
558 );
559
560 let addr = Address::from_str("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k").unwrap();
561 let json = Json::from_serialize(&addr).unwrap();
562 assert_eq!(json.string(), Some("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"));
563 let into: Address = json.into_deserialize().unwrap();
564 assert_eq!(addr.to_string(), into.to_string());
565 assert_eq!(
566 into.script_pubkey(),
567 hex_script!("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087")
568 );
569
570 let addr = Address::from_str("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7").unwrap();
571 let json = Json::from_serialize(&addr).unwrap();
572 assert_eq!(json.string(), Some("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7"));
573 let into: Address = json.into_deserialize().unwrap();
574 assert_eq!(addr.to_string(), into.to_string());
575 assert_eq!(
576 into.script_pubkey(),
577 hex_script!("00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262")
578 );
579
580 let addr = Address::from_str("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl").unwrap();
581 let json = Json::from_serialize(&addr).unwrap();
582 assert_eq!(json.string(), Some("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl"));
583 let into: Address = json.into_deserialize().unwrap();
584 assert_eq!(addr.to_string(), into.to_string());
585 assert_eq!(
586 into.script_pubkey(),
587 hex_script!("001454d26dddb59c7073c6a197946ea1841951fa7a74")
588 );
589 }
590}