support for compressed publics
This commit is contained in:
parent
aff17ede5c
commit
c86ec93b60
|
@ -2,6 +2,7 @@ use hex::{ToHex, FromHex};
|
|||
|
||||
pub type H160 = [u8; 20];
|
||||
pub type H256 = [u8; 32];
|
||||
pub type H264 = [u8; 33];
|
||||
pub type H512 = [u8; 64];
|
||||
pub type H520 = [u8; 65];
|
||||
|
||||
|
|
|
@ -16,10 +16,17 @@ pub struct KeyPair {
|
|||
public: Public,
|
||||
}
|
||||
|
||||
impl fmt::Debug for KeyPair {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(self.private.fmt(f));
|
||||
writeln!(f, "public: {:?}", self.public)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for KeyPair {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(writeln!(f, "private: {}", self.private.to_string()));
|
||||
writeln!(f, "public: {}", self.public.to_hex())
|
||||
try!(writeln!(f, "private: {}", self.private));
|
||||
writeln!(f, "public: {}", self.public)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,10 +36,17 @@ impl KeyPair {
|
|||
let s: key::SecretKey = try!(key::SecretKey::from_slice(context, &private.secret));
|
||||
let pub_key = try!(key::PublicKey::from_secret_key(context, &s));
|
||||
// TODO: take into account private field `compressed`
|
||||
let serialized = pub_key.serialize_vec(context, false);
|
||||
let serialized = pub_key.serialize_vec(context, private.compressed);
|
||||
|
||||
let mut public = [0u8; 65];
|
||||
public.copy_from_slice(&serialized[0..65]);
|
||||
let public = if private.compressed {
|
||||
let mut public = [0u8; 33];
|
||||
public.copy_from_slice(&serialized[0..33]);
|
||||
Public::Compressed(public)
|
||||
} else {
|
||||
let mut public = [0u8; 65];
|
||||
public.copy_from_slice(&serialized[0..65]);
|
||||
Public::Normal(public)
|
||||
};
|
||||
|
||||
let keypair = KeyPair {
|
||||
private: private,
|
||||
|
@ -56,7 +70,7 @@ impl KeyPair {
|
|||
secret: secret,
|
||||
compressed: false,
|
||||
},
|
||||
public: public,
|
||||
public: Public::Normal(public),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,11 +99,30 @@ impl KeyPair {
|
|||
mod tests {
|
||||
use super::KeyPair;
|
||||
|
||||
/// Tests from:
|
||||
/// https://github.com/bitcoin/bitcoin/blob/a6a860796a44a2805a58391a009ba22752f64e32/src/test/key_tests.cpp
|
||||
const SECRET_0: &'static str = "5KSCKP8NUyBZPCCQusxRwgmz9sfvJQEgbGukmmHepWw5Bzp95mu";
|
||||
const SECRET_1: &'static str = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj";
|
||||
const SECRET_2: &'static str = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3";
|
||||
const SECRET_3: &'static str = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw";
|
||||
const SECRET_4: &'static str = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g";
|
||||
const ADDRESS_0: &'static str = "16meyfSoQV6twkAAxPe51RtMVz7PGRmWna";
|
||||
const ADDRESS_1: &'static str = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ";
|
||||
const ADDRESS_2: &'static str = "1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ";
|
||||
const ADDRESS_3: &'static str = "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs";
|
||||
const ADDRESS_4: &'static str = "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs";
|
||||
|
||||
fn check_addresses(secret: &'static str, address: &'static str) -> bool {
|
||||
let kp = KeyPair::from_private(secret.into()).unwrap();
|
||||
kp.address() == address.into()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generating_address() {
|
||||
// secret: 5KSCKP8NUyBZPCCQusxRwgmz9sfvJQEgbGukmmHepWw5Bzp95mu
|
||||
// address: 16meyfSoQV6twkAAxPe51RtMVz7PGRmWna
|
||||
let kp = KeyPair::from_private("5KSCKP8NUyBZPCCQusxRwgmz9sfvJQEgbGukmmHepWw5Bzp95mu".into()).unwrap();
|
||||
assert_eq!(kp.address(), "16meyfSoQV6twkAAxPe51RtMVz7PGRmWna".into());
|
||||
assert!(check_addresses(SECRET_0, ADDRESS_0));
|
||||
assert!(check_addresses(SECRET_1, ADDRESS_1));
|
||||
assert!(check_addresses(SECRET_2, ADDRESS_2));
|
||||
assert!(check_addresses(SECRET_3, ADDRESS_3));
|
||||
assert!(check_addresses(SECRET_4, ADDRESS_4));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ pub mod generator;
|
|||
pub mod keypair;
|
||||
mod error;
|
||||
mod private;
|
||||
mod public;
|
||||
|
||||
pub use self::address::{Type, Address};
|
||||
pub use self::checksum::checksum;
|
||||
|
@ -20,11 +21,11 @@ pub use self::display::DisplayLayout;
|
|||
pub use self::keypair::KeyPair;
|
||||
pub use self::error::Error;
|
||||
pub use self::private::Private;
|
||||
pub use self::public::Public;
|
||||
|
||||
use hash::{H160, H256, H520};
|
||||
pub type AddressHash = H160;
|
||||
pub type Secret = H256;
|
||||
pub type Public = H520;
|
||||
|
||||
use secp256k1;
|
||||
lazy_static! {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use hex::ToHex;
|
||||
use base58::{ToBase58, FromBase58};
|
||||
use network::Network;
|
||||
use keys::{Secret, DisplayLayout, checksum, Error};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(PartialEq)]
|
||||
pub struct Private {
|
||||
/// The network on which this key should be used.
|
||||
pub network: Network,
|
||||
|
@ -69,6 +70,14 @@ impl DisplayLayout for Private {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Private {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(writeln!(f, "network: {:?}", self.network));
|
||||
try!(writeln!(f, "secret: {}", self.secret.to_hex()));
|
||||
writeln!(f, "compressed: {}", self.compressed)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Private {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.layout().to_base58().fmt(f)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use hex::ToHex;
|
||||
use hash::{H264, H520};
|
||||
|
||||
pub enum Public {
|
||||
Normal(H520),
|
||||
Compressed(H264),
|
||||
}
|
||||
|
||||
impl Deref for Public {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match *self {
|
||||
Public::Normal(ref hash) => hash,
|
||||
Public::Compressed(ref hash) => hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Public {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Public::Normal(ref hash) => writeln!(f, "normal: {}", hash.to_hex()),
|
||||
Public::Compressed(ref hash) => writeln!(f, "normal: {}", hash.to_hex()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Public {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.to_hex().fmt(f)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue