Implement `Display` instead of `ToString` for `Address` and `PrivKey`.

Signed-off-by: Jean Pierre Dudey <jeandudey@hotmail.com>
This commit is contained in:
Jean Pierre Dudey 2018-08-20 15:40:00 -04:00
parent 2d961412af
commit df7f084e96
3 changed files with 43 additions and 13 deletions

View File

@ -16,8 +16,8 @@
//! Support for ordinary base58 Bitcoin addresses and private keys
//!
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use std::string::ToString;
use bitcoin_bech32::{self, WitnessProgram, u5};
use secp256k1::key::PublicKey;
@ -203,8 +203,8 @@ impl Address {
}
}
impl ToString for Address {
fn to_string(&self) -> String {
impl Display for Address {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
match self.payload {
// note: serialization for pay-to-pk is defined, but is irreversible
Payload::Pubkey(ref pk) => {
@ -215,7 +215,7 @@ impl ToString for Address {
Network::Testnet | Network::Regtest => 111,
};
prefixed[1..].copy_from_slice(&hash[..]);
base58::check_encode_slice(&prefixed[..])
base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
},
Payload::PubkeyHash(ref hash) => {
let mut prefixed = [0; 21];
@ -224,7 +224,7 @@ impl ToString for Address {
Network::Testnet | Network::Regtest => 111,
};
prefixed[1..].copy_from_slice(&hash[..]);
base58::check_encode_slice(&prefixed[..])
base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
},
Payload::ScriptHash(ref hash) => {
let mut prefixed = [0; 21];
@ -233,10 +233,10 @@ impl ToString for Address {
Network::Testnet | Network::Regtest => 196,
};
prefixed[1..].copy_from_slice(&hash[..]);
base58::check_encode_slice(&prefixed[..])
base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
},
Payload::WitnessProgram(ref witprog) => {
witprog.to_address()
fmt.write_str(&witprog.to_address())
},
}
}

View File

@ -14,7 +14,7 @@
//! Base58 encoder and decoder
use std::{error, fmt};
use std::{error, fmt, str};
use byteorder::{ByteOrder, LittleEndian};
use util::hash::Sha256dHash;
@ -134,7 +134,7 @@ pub fn from_check(data: &str) -> Result<Vec<u8>, Error> {
Ok(ret)
}
fn encode_iter<I>(data: I) -> String
fn encode_iter_utf8<I>(data: I) -> Vec<u8>
where
I: Iterator<Item = u8> + Clone,
{
@ -173,9 +173,26 @@ where
for ch in ret.iter_mut() {
*ch = BASE58_CHARS[*ch as usize];
}
ret
}
fn encode_iter<I>(data: I) -> String
where
I: Iterator<Item = u8> + Clone,
{
let ret = encode_iter_utf8(data);
String::from_utf8(ret).unwrap()
}
/// Directly encode a slice as base58 into a `Formatter`.
fn encode_iter_to_fmt<I>(fmt: &mut fmt::Formatter, data: I) -> fmt::Result
where
I: Iterator<Item = u8> + Clone,
{
let ret = encode_iter_utf8(data);
fmt.write_str(str::from_utf8(&ret).unwrap())
}
/// Directly encode a slice as base58
pub fn encode_slice(data: &[u8]) -> String {
encode_iter(data.iter().cloned())
@ -192,6 +209,16 @@ pub fn check_encode_slice(data: &[u8]) -> String {
)
}
/// Obtain a string with the base58check encoding of a slice
/// (Tack the first 4 256-digits of the object's Bitcoin hash onto the end.)
pub fn check_encode_slice_to_fmt(fmt: &mut fmt::Formatter, data: &[u8]) -> fmt::Result {
let checksum = Sha256dHash::from_data(&data);
let iter = data.iter()
.cloned()
.chain(checksum[0..4].iter().cloned());
encode_iter_to_fmt(fmt, iter)
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -15,6 +15,8 @@
//!
//! A private key represents the secret data associated with its proposed use
//!
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use util::Error;
use secp256k1::{self, Secp256k1};
@ -92,20 +94,21 @@ impl Privkey {
}
}
impl ToString for Privkey {
fn to_string(&self) -> String {
impl Display for Privkey {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
let mut ret = [0; 34];
ret[0] = match self.network {
Network::Bitcoin => 128,
Network::Testnet | Network::Regtest => 239,
};
ret[1..33].copy_from_slice(&self.key[..]);
if self.compressed {
let privkey = if self.compressed {
ret[33] = 1;
base58::check_encode_slice(&ret[..])
} else {
base58::check_encode_slice(&ret[..33])
}
};
fmt.write_str(&privkey)
}
}