Implement `Display` instead of `ToString` for `Address` and `PrivKey`.
Signed-off-by: Jean Pierre Dudey <jeandudey@hotmail.com>
This commit is contained in:
parent
2d961412af
commit
df7f084e96
|
@ -16,8 +16,8 @@
|
||||||
//! Support for ordinary base58 Bitcoin addresses and private keys
|
//! Support for ordinary base58 Bitcoin addresses and private keys
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::string::ToString;
|
|
||||||
|
|
||||||
use bitcoin_bech32::{self, WitnessProgram, u5};
|
use bitcoin_bech32::{self, WitnessProgram, u5};
|
||||||
use secp256k1::key::PublicKey;
|
use secp256k1::key::PublicKey;
|
||||||
|
@ -203,8 +203,8 @@ impl Address {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Address {
|
impl Display for Address {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||||
match self.payload {
|
match self.payload {
|
||||||
// note: serialization for pay-to-pk is defined, but is irreversible
|
// note: serialization for pay-to-pk is defined, but is irreversible
|
||||||
Payload::Pubkey(ref pk) => {
|
Payload::Pubkey(ref pk) => {
|
||||||
|
@ -215,7 +215,7 @@ impl ToString for Address {
|
||||||
Network::Testnet | Network::Regtest => 111,
|
Network::Testnet | Network::Regtest => 111,
|
||||||
};
|
};
|
||||||
prefixed[1..].copy_from_slice(&hash[..]);
|
prefixed[1..].copy_from_slice(&hash[..]);
|
||||||
base58::check_encode_slice(&prefixed[..])
|
base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
|
||||||
},
|
},
|
||||||
Payload::PubkeyHash(ref hash) => {
|
Payload::PubkeyHash(ref hash) => {
|
||||||
let mut prefixed = [0; 21];
|
let mut prefixed = [0; 21];
|
||||||
|
@ -224,7 +224,7 @@ impl ToString for Address {
|
||||||
Network::Testnet | Network::Regtest => 111,
|
Network::Testnet | Network::Regtest => 111,
|
||||||
};
|
};
|
||||||
prefixed[1..].copy_from_slice(&hash[..]);
|
prefixed[1..].copy_from_slice(&hash[..]);
|
||||||
base58::check_encode_slice(&prefixed[..])
|
base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
|
||||||
},
|
},
|
||||||
Payload::ScriptHash(ref hash) => {
|
Payload::ScriptHash(ref hash) => {
|
||||||
let mut prefixed = [0; 21];
|
let mut prefixed = [0; 21];
|
||||||
|
@ -233,10 +233,10 @@ impl ToString for Address {
|
||||||
Network::Testnet | Network::Regtest => 196,
|
Network::Testnet | Network::Regtest => 196,
|
||||||
};
|
};
|
||||||
prefixed[1..].copy_from_slice(&hash[..]);
|
prefixed[1..].copy_from_slice(&hash[..]);
|
||||||
base58::check_encode_slice(&prefixed[..])
|
base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
|
||||||
},
|
},
|
||||||
Payload::WitnessProgram(ref witprog) => {
|
Payload::WitnessProgram(ref witprog) => {
|
||||||
witprog.to_address()
|
fmt.write_str(&witprog.to_address())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
//! Base58 encoder and decoder
|
//! Base58 encoder and decoder
|
||||||
|
|
||||||
use std::{error, fmt};
|
use std::{error, fmt, str};
|
||||||
|
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
|
@ -134,7 +134,7 @@ pub fn from_check(data: &str) -> Result<Vec<u8>, Error> {
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_iter<I>(data: I) -> String
|
fn encode_iter_utf8<I>(data: I) -> Vec<u8>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = u8> + Clone,
|
I: Iterator<Item = u8> + Clone,
|
||||||
{
|
{
|
||||||
|
@ -173,9 +173,26 @@ where
|
||||||
for ch in ret.iter_mut() {
|
for ch in ret.iter_mut() {
|
||||||
*ch = BASE58_CHARS[*ch as usize];
|
*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()
|
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
|
/// Directly encode a slice as base58
|
||||||
pub fn encode_slice(data: &[u8]) -> String {
|
pub fn encode_slice(data: &[u8]) -> String {
|
||||||
encode_iter(data.iter().cloned())
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
//!
|
//!
|
||||||
//! A private key represents the secret data associated with its proposed use
|
//! A private key represents the secret data associated with its proposed use
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use util::Error;
|
use util::Error;
|
||||||
use secp256k1::{self, Secp256k1};
|
use secp256k1::{self, Secp256k1};
|
||||||
|
@ -92,20 +94,21 @@ impl Privkey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Privkey {
|
impl Display for Privkey {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||||
let mut ret = [0; 34];
|
let mut ret = [0; 34];
|
||||||
ret[0] = match self.network {
|
ret[0] = match self.network {
|
||||||
Network::Bitcoin => 128,
|
Network::Bitcoin => 128,
|
||||||
Network::Testnet | Network::Regtest => 239,
|
Network::Testnet | Network::Regtest => 239,
|
||||||
};
|
};
|
||||||
ret[1..33].copy_from_slice(&self.key[..]);
|
ret[1..33].copy_from_slice(&self.key[..]);
|
||||||
if self.compressed {
|
let privkey = if self.compressed {
|
||||||
ret[33] = 1;
|
ret[33] = 1;
|
||||||
base58::check_encode_slice(&ret[..])
|
base58::check_encode_slice(&ret[..])
|
||||||
} else {
|
} else {
|
||||||
base58::check_encode_slice(&ret[..33])
|
base58::check_encode_slice(&ret[..33])
|
||||||
}
|
};
|
||||||
|
fmt.write_str(&privkey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue