keypair generation in progress
This commit is contained in:
parent
d7f650db51
commit
e39f37fac7
|
@ -1,19 +0,0 @@
|
|||
//! A Bitcoin address, or simply address, is an identifier of 26-35 alphanumeric characters, beginning with the number 1
|
||||
//! or 3, that represents a possible destination for a bitcoin payment.
|
||||
//!
|
||||
//! https://en.bitcoin.it/wiki/Address
|
||||
|
||||
/// There are two address formats currently in use.
|
||||
/// https://bitcoin.org/en/developer-reference#address-conversion
|
||||
pub enum Format {
|
||||
/// Pay to PubKey Hash
|
||||
/// Common P2PKH which begin with the number 1, eg: 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2.
|
||||
/// https://bitcoin.org/en/glossary/p2pkh-address
|
||||
P2PKH,
|
||||
/// Pay to Script Hash
|
||||
/// Newer P2SH type starting with the number 3, eg: 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy.
|
||||
/// https://bitcoin.org/en/glossary/p2sh-address
|
||||
P2SH,
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
//! A Bitcoin address, or simply address, is an identifier of 26-35 alphanumeric characters, beginning with the number 1
|
||||
//! or 3, that represents a possible destination for a bitcoin payment.
|
||||
//!
|
||||
//! https://en.bitcoin.it/wiki/Address
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use base58::ToBase58;
|
||||
use network::Network;
|
||||
use hash::H160;
|
||||
use keys::{DisplayLayout, checksum};
|
||||
|
||||
/// There are two address formats currently in use.
|
||||
/// https://bitcoin.org/en/developer-reference#address-conversion
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum Type {
|
||||
/// Pay to PubKey Hash
|
||||
/// Common P2PKH which begin with the number 1, eg: 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2.
|
||||
/// https://bitcoin.org/en/glossary/p2pkh-address
|
||||
P2PKH,
|
||||
/// Pay to Script Hash
|
||||
/// Newer P2SH type starting with the number 3, eg: 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy.
|
||||
/// https://bitcoin.org/en/glossary/p2sh-address
|
||||
P2SH,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Address {
|
||||
/// The type of the address.
|
||||
pub kind: Type,
|
||||
/// The network of the address.
|
||||
pub network: Network,
|
||||
/// Public key hash.
|
||||
pub hash: H160,
|
||||
}
|
||||
|
||||
pub struct AddressDisplayLayout([u8; 25]);
|
||||
|
||||
impl Deref for AddressDisplayLayout {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayLayout for Address {
|
||||
type Target = AddressDisplayLayout;
|
||||
|
||||
fn layout(&self) -> Self::Target {
|
||||
let mut result = [0u8; 25];
|
||||
|
||||
result[0] = match (self.network, self.kind) {
|
||||
(Network::Mainnet, Type::P2PKH) => 0,
|
||||
(Network::Mainnet, Type::P2SH) => 5,
|
||||
(Network::Testnet, Type::P2PKH) => 111,
|
||||
(Network::Testnet, Type::P2SH) => 196,
|
||||
};
|
||||
|
||||
result[1..21].copy_from_slice(&self.hash);
|
||||
let cs = checksum(&result[0..21]);
|
||||
result[21..25].copy_from_slice(&cs);
|
||||
AddressDisplayLayout(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Address {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.layout().to_base58().fmt(f)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
use crypto::dhash;
|
||||
|
||||
/// Data checksum
|
||||
pub fn checksum(data: &[u8]) -> [u8; 4] {
|
||||
let mut result = [0u8; 4];
|
||||
// TODO: check if this checksum is valid
|
||||
result.copy_from_slice(&dhash(data)[28..]);
|
||||
result
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
pub trait DisplayLayout {
|
||||
type Target: Deref<Target = [u8]>;
|
||||
|
||||
fn layout(&self) -> Self::Target;
|
||||
}
|
|
@ -1,10 +1,21 @@
|
|||
//! Bitcoin KeyPair
|
||||
//!
|
||||
//! Fields:
|
||||
//! - secret - 32 bytes
|
||||
//! - public - 65 bytes
|
||||
//! - private - secret with additional network identifier (and compressed flag?)
|
||||
//! - address_hash - 20 bytes derived from public
|
||||
//! - address - address_hash with network identifier and format type
|
||||
|
||||
use std::fmt;
|
||||
use rustc_serialize::hex::ToHex;
|
||||
use rcrypto::sha2::Sha256;
|
||||
use rcrypto::ripemd160::Ripemd160;
|
||||
use rcrypto::digest::Digest;
|
||||
use secp256k1::key;
|
||||
use keys::{Secret, Public, Error, SECP256K1, Address};
|
||||
use hash::H160;
|
||||
use network::Network;
|
||||
use keys::{Secret, Public, Error, SECP256K1, Address, Type};
|
||||
|
||||
pub struct KeyPair {
|
||||
secret: Secret,
|
||||
|
@ -51,7 +62,7 @@ impl KeyPair {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn address(&self) -> Address {
|
||||
pub fn address_hash(&self) -> H160 {
|
||||
let mut tmp = [0u8; 32];
|
||||
let mut result = [0u8; 20];
|
||||
let mut sha2 = Sha256::new();
|
||||
|
@ -62,12 +73,20 @@ impl KeyPair {
|
|||
rmd.result(&mut result);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn address(&self, network: Network) -> Address {
|
||||
Address {
|
||||
kind: Type::P2PKH,
|
||||
network: network,
|
||||
hash: self.address_hash(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::KeyPair;
|
||||
use base58::{ToBase58, FromBase58};
|
||||
use base58::{FromBase58};
|
||||
|
||||
#[test]
|
||||
fn test_generating_address() {
|
||||
|
@ -78,6 +97,6 @@ mod tests {
|
|||
let mut address = [0u8; 20];
|
||||
address.copy_from_slice(&"16meyfSoQV6twkAAxPe51RtMVz7PGRmWna".from_base58().unwrap()[1..21]);
|
||||
let kp = KeyPair::from_secret(secret).unwrap();
|
||||
assert_eq!(kp.address(), address);
|
||||
assert_eq!(kp.address_hash(), address);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
mod address;
|
||||
mod checksum;
|
||||
pub mod display;
|
||||
pub mod generator;
|
||||
pub mod keypair;
|
||||
mod error;
|
||||
mod private;
|
||||
|
||||
use secp256k1;
|
||||
use hash::{H160, H256, H520};
|
||||
use hash::{H256, H520};
|
||||
pub use self::address::{Type, Address};
|
||||
pub use self::checksum::checksum;
|
||||
pub use self::display::DisplayLayout;
|
||||
pub use self::keypair::KeyPair;
|
||||
pub use self::error::Error;
|
||||
pub use self::private::Private;
|
||||
|
||||
pub type Address = H160;
|
||||
pub type Secret = H256;
|
||||
pub type Public = H520;
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
use std::fmt;
|
||||
use base58::ToBase58;
|
||||
use network::Network;
|
||||
use keys::{Secret, DisplayLayout};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Private {
|
||||
/// The network on which this key should be used.
|
||||
pub network: Network,
|
||||
/// ECDSA key.
|
||||
pub secret: Secret,
|
||||
/// True if this private key represents a compressed address.
|
||||
pub compressed: bool,
|
||||
}
|
||||
|
||||
impl DisplayLayout for Private {
|
||||
type Target = Vec<u8>;
|
||||
|
||||
fn layout(&self) -> Self::Target {
|
||||
let mut result = vec![];
|
||||
let network_byte = match self.network {
|
||||
Network::Mainnet => 128,
|
||||
Network::Testnet => 239,
|
||||
};
|
||||
|
||||
result.push(network_byte);
|
||||
result.extend(&self.secret);
|
||||
if self.compressed {
|
||||
result.push(1);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Private {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.layout().to_base58().fmt(f)
|
||||
}
|
||||
}
|
|
@ -10,7 +10,6 @@ extern crate secp256k1;
|
|||
extern crate base58;
|
||||
|
||||
pub mod keys;
|
||||
pub mod address;
|
||||
pub mod block;
|
||||
pub mod block_header;
|
||||
pub mod compact_integer;
|
||||
|
|
|
@ -5,7 +5,7 @@ const MAGIC_TESTNET: u32 = 0x0709110B;
|
|||
|
||||
/// Bitcoin network
|
||||
/// https://bitcoin.org/en/glossary/mainnet
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum Network {
|
||||
/// The original and main network for Bitcoin transactions, where satoshis have real economic value.
|
||||
Mainnet,
|
||||
|
|
Loading…
Reference in New Issue