diff --git a/src/util/hash.rs b/src/util/hash.rs index 84c95ef..3af6ace 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -44,6 +44,7 @@ impl ::std::fmt::Show for Sha256dHash { /// A RIPEMD-160 hash pub struct Ripemd160Hash([u8, ..20]); +impl_array_newtype!(Ripemd160Hash, u8, 20) /// A "hasher" which just truncates pub struct DumbHasher; diff --git a/src/wallet/address.rs b/src/wallet/address.rs new file mode 100644 index 0000000..19cf429 --- /dev/null +++ b/src/wallet/address.rs @@ -0,0 +1,88 @@ +// Rust Bitcoin Library +// Written in 2014 by +// Andrew Poelstra +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +//! # Addresses +//! +//! Support for ordinary base58 Bitcoin addresses +//! + +use network::constants::{Network, Bitcoin, BitcoinTestnet}; +use util::hash::Ripemd160Hash; +use util::base58::{Base58Error, + InvalidLength, InvalidVersion, + FromBase58, ToBase58}; + +#[deriving(Clone, PartialEq, Eq)] +/// A Bitcoin address +pub struct Address { + network: Network, + hash: Ripemd160Hash +} + +impl ToBase58 for Address { + fn base58_layout(&self) -> Vec { + let mut ret = vec![ + match self.network { + Bitcoin => 0, + BitcoinTestnet => 111 + } + ]; + ret.push_all(self.hash.as_slice()); + ret + } +} + +impl FromBase58 for Address { + fn from_base58_layout(data: Vec) -> Result { + if data.len() != 21 { + return Err(InvalidLength(data.len())); + } + + Ok(Address { + network: match data[0] { + 0 => Bitcoin, + 111 => BitcoinTestnet, + x => { return Err(InvalidVersion(vec![x])); } + }, + hash: Ripemd160Hash::from_slice(data.slice_from(1)) + }) + } +} + +impl ::std::fmt::Show for Address { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self.to_base58check()) + } +} + +#[cfg(test)] +mod tests { + use serialize::hex::FromHex; + + use network::constants::Bitcoin; + use util::hash::Ripemd160Hash; + use util::base58::{FromBase58, ToBase58}; + use super::Address; + + #[test] + fn test_address_58() { + let addr = Address { + network: Bitcoin, + hash: Ripemd160Hash::from_slice("162c5ea71c0b23f5b9022ef047c4a86470a5b070".from_hex().unwrap().as_slice()) + }; + + assert_eq!(addr.to_base58check().as_slice(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"); + assert_eq!(FromBase58::from_base58check("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"), Ok(addr)); + } +} + diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index e3469e4..65e9731 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -16,5 +16,6 @@ //! //! Wallet, keys and addresses +pub mod address; pub mod bip32;