Fix for upstream, add some address generation benchmarks
This commit is contained in:
parent
931df9f68d
commit
f66b4ff6b3
|
@ -1365,7 +1365,7 @@ pub fn read_uint<'a, I:Iterator<&'a u8>>(mut iter: I, size: uint)
|
||||||
|
|
||||||
/// Check a signature -- returns an error that is currently just translated
|
/// Check a signature -- returns an error that is currently just translated
|
||||||
/// into a 0/1 to push onto the script stack
|
/// into a 0/1 to push onto the script stack
|
||||||
fn check_signature(secp: &Secp256k1, sig_slice: &[u8], pk_slice: &[u8], script: Vec<u8>,
|
fn check_signature(sig_slice: &[u8], pk_slice: &[u8], script: Vec<u8>,
|
||||||
tx: &Transaction, input_index: uint) -> Result<(), ScriptError> {
|
tx: &Transaction, input_index: uint) -> Result<(), ScriptError> {
|
||||||
|
|
||||||
// Check public key
|
// Check public key
|
||||||
|
@ -1451,7 +1451,7 @@ fn check_signature(secp: &Secp256k1, sig_slice: &[u8], pk_slice: &[u8], script:
|
||||||
serialize(&Sha256dHash::from_data(data_to_sign.as_slice())).unwrap()
|
serialize(&Sha256dHash::from_data(data_to_sign.as_slice())).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
secp.verify(signature_hash.as_slice(), sig_slice, &pubkey).map_err(|e| EcdsaError(e))
|
Secp256k1::verify(signature_hash.as_slice(), sig_slice, &pubkey).map_err(|e| EcdsaError(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Macro to translate English stack instructions into Rust code.
|
// Macro to translate English stack instructions into Rust code.
|
||||||
|
@ -1678,7 +1678,6 @@ impl Script {
|
||||||
mut trace: Option<&mut Vec<TraceIteration>>)
|
mut trace: Option<&mut Vec<TraceIteration>>)
|
||||||
-> Result<(), ScriptError> {
|
-> Result<(), ScriptError> {
|
||||||
let &Script(ref raw) = self;
|
let &Script(ref raw) = self;
|
||||||
let secp = Secp256k1::new();
|
|
||||||
|
|
||||||
let mut codeseparator_index = 0u;
|
let mut codeseparator_index = 0u;
|
||||||
let mut exec_stack = vec![];
|
let mut exec_stack = vec![];
|
||||||
|
@ -1916,7 +1915,7 @@ impl Script {
|
||||||
// Otherwise unwrap it
|
// Otherwise unwrap it
|
||||||
let (tx, input_index) = input_context.unwrap();
|
let (tx, input_index) = input_context.unwrap();
|
||||||
|
|
||||||
match check_signature(&secp, sig_slice, pk_slice, script, tx, input_index) {
|
match check_signature( sig_slice, pk_slice, script, tx, input_index) {
|
||||||
Ok(()) => stack.push(Slice(SCRIPT_TRUE)),
|
Ok(()) => stack.push(Slice(SCRIPT_TRUE)),
|
||||||
_ => stack.push(Slice(SCRIPT_FALSE)),
|
_ => stack.push(Slice(SCRIPT_FALSE)),
|
||||||
}
|
}
|
||||||
|
@ -1977,7 +1976,7 @@ impl Script {
|
||||||
// Try to validate the signature with the given key
|
// Try to validate the signature with the given key
|
||||||
(Some(k), Some(s)) => {
|
(Some(k), Some(s)) => {
|
||||||
// Move to the next signature if it is valid for the current key
|
// Move to the next signature if it is valid for the current key
|
||||||
if check_signature(&secp, s.as_slice(), k.as_slice(),
|
if check_signature(s.as_slice(), k.as_slice(),
|
||||||
script.clone(), tx, input_index).is_ok() {
|
script.clone(), tx, input_index).is_ok() {
|
||||||
sig = sig_iter.next();
|
sig = sig_iter.next();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ extern crate rand;
|
||||||
extern crate rustrt;
|
extern crate rustrt;
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
extern crate sync;
|
extern crate sync;
|
||||||
|
extern crate test;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
|
||||||
extern crate secp256k1 = "bitcoin-secp256k1-rs";
|
extern crate secp256k1 = "bitcoin-secp256k1-rs";
|
||||||
|
|
|
@ -25,7 +25,8 @@ use std::hash;
|
||||||
use serialize::json::{mod, ToJson};
|
use serialize::json::{mod, ToJson};
|
||||||
|
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha2;
|
use crypto::sha2::Sha256;
|
||||||
|
use crypto::ripemd160::Ripemd160;
|
||||||
|
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder};
|
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder};
|
||||||
|
@ -130,6 +131,19 @@ impl Default for DumbHasher {
|
||||||
fn default() -> DumbHasher { DumbHasher }
|
fn default() -> DumbHasher { DumbHasher }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ripemd160Hash {
|
||||||
|
/// Create a hash by hashing some data
|
||||||
|
pub fn from_data(data: &[u8]) -> Ripemd160Hash {
|
||||||
|
let mut ret = [0, ..20];
|
||||||
|
let mut rmd = Ripemd160::new();
|
||||||
|
rmd.input(data);
|
||||||
|
rmd.result(ret.as_mut_slice());
|
||||||
|
Ripemd160Hash(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This doesn't make much sense to me, but is implicit behaviour
|
||||||
|
// in the C++ reference client
|
||||||
impl Default for Sha256dHash {
|
impl Default for Sha256dHash {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Sha256dHash { Sha256dHash([0u8, ..32]) }
|
fn default() -> Sha256dHash { Sha256dHash([0u8, ..32]) }
|
||||||
|
@ -139,7 +153,7 @@ impl Sha256dHash {
|
||||||
/// Create a hash by hashing some data
|
/// Create a hash by hashing some data
|
||||||
pub fn from_data(data: &[u8]) -> Sha256dHash {
|
pub fn from_data(data: &[u8]) -> Sha256dHash {
|
||||||
let Sha256dHash(mut ret): Sha256dHash = Default::default();
|
let Sha256dHash(mut ret): Sha256dHash = Default::default();
|
||||||
let mut sha2 = sha2::Sha256::new();
|
let mut sha2 = Sha256::new();
|
||||||
sha2.input(data);
|
sha2.input(data);
|
||||||
sha2.result(ret.as_mut_slice());
|
sha2.result(ret.as_mut_slice());
|
||||||
sha2.reset();
|
sha2.reset();
|
||||||
|
|
|
@ -16,6 +16,12 @@
|
||||||
//! Support for ordinary base58 Bitcoin addresses
|
//! Support for ordinary base58 Bitcoin addresses
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use secp256k1::key::PublicKey;
|
||||||
|
use crypto::digest::Digest;
|
||||||
|
use crypto::sha2::Sha256;
|
||||||
|
|
||||||
|
use blockdata::script::Script;
|
||||||
|
use blockdata::opcodes::all;
|
||||||
use network::constants::{Network, Bitcoin, BitcoinTestnet};
|
use network::constants::{Network, Bitcoin, BitcoinTestnet};
|
||||||
use util::hash::Ripemd160Hash;
|
use util::hash::Ripemd160Hash;
|
||||||
use util::base58::{Base58Error,
|
use util::base58::{Base58Error,
|
||||||
|
@ -29,6 +35,31 @@ pub struct Address {
|
||||||
hash: Ripemd160Hash
|
hash: Ripemd160Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Address {
|
||||||
|
/// Creates an address from a public key
|
||||||
|
pub fn from_key(network: Network, pk: &PublicKey) -> Address {
|
||||||
|
let mut sha = Sha256::new();
|
||||||
|
let mut out = [0, ..32];
|
||||||
|
sha.input(pk.as_slice());
|
||||||
|
sha.result(out.as_mut_slice());
|
||||||
|
Address {
|
||||||
|
network: network,
|
||||||
|
hash: Ripemd160Hash::from_data(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a script pubkey spending to this address
|
||||||
|
pub fn script_pubkey(&self) -> Script {
|
||||||
|
let mut script = Script::new();
|
||||||
|
script.push_opcode(all::OP_DUP);
|
||||||
|
script.push_opcode(all::OP_HASH160);
|
||||||
|
script.push_slice(self.hash.as_slice());
|
||||||
|
script.push_opcode(all::OP_EQUALVERIFY);
|
||||||
|
script.push_opcode(all::OP_CHECKSIG);
|
||||||
|
script
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToBase58 for Address {
|
impl ToBase58 for Address {
|
||||||
fn base58_layout(&self) -> Vec<u8> {
|
fn base58_layout(&self) -> Vec<u8> {
|
||||||
let mut ret = vec![
|
let mut ret = vec![
|
||||||
|
@ -68,6 +99,9 @@ impl ::std::fmt::Show for Address {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serialize::hex::FromHex;
|
use serialize::hex::FromHex;
|
||||||
|
use test::{Bencher, black_box};
|
||||||
|
|
||||||
|
use secp256k1::Secp256k1;
|
||||||
|
|
||||||
use network::constants::Bitcoin;
|
use network::constants::Bitcoin;
|
||||||
use util::hash::Ripemd160Hash;
|
use util::hash::Ripemd160Hash;
|
||||||
|
@ -84,5 +118,42 @@ mod tests {
|
||||||
assert_eq!(addr.to_base58check().as_slice(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM");
|
assert_eq!(addr.to_base58check().as_slice(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM");
|
||||||
assert_eq!(FromBase58::from_base58check("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"), Ok(addr));
|
assert_eq!(FromBase58::from_base58check("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"), Ok(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn generate_address(bh: &mut Bencher) {
|
||||||
|
let mut s = Secp256k1::new().unwrap();
|
||||||
|
bh.iter( || {
|
||||||
|
let (sk, pk) = s.generate_keypair(true);
|
||||||
|
black_box(sk);
|
||||||
|
black_box(pk);
|
||||||
|
let addr = Address::from_key(Bitcoin, &pk);
|
||||||
|
black_box(addr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn generate_uncompressed_address(bh: &mut Bencher) {
|
||||||
|
let mut s = Secp256k1::new().unwrap();
|
||||||
|
bh.iter( || {
|
||||||
|
let (sk, pk) = s.generate_keypair(false);
|
||||||
|
black_box(sk);
|
||||||
|
black_box(pk);
|
||||||
|
let addr = Address::from_key(Bitcoin, &pk);
|
||||||
|
black_box(addr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn generate_sequential_address(bh: &mut Bencher) {
|
||||||
|
let mut s = Secp256k1::new().unwrap();
|
||||||
|
let (sk, _) = s.generate_keypair(true);
|
||||||
|
let mut iter = sk.sequence(true);
|
||||||
|
bh.iter( || {
|
||||||
|
let (sk, pk) = iter.next().unwrap();
|
||||||
|
black_box(sk);
|
||||||
|
let addr = Address::from_key(Bitcoin, &pk);
|
||||||
|
black_box(addr);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,6 +353,7 @@ impl FromBase58 for ExtendedPubKey {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serialize::hex::FromHex;
|
use serialize::hex::FromHex;
|
||||||
|
use test::{Bencher, black_box};
|
||||||
|
|
||||||
use network::constants::{Network, Bitcoin};
|
use network::constants::{Network, Bitcoin};
|
||||||
use util::base58::{FromBase58, ToBase58};
|
use util::base58::{FromBase58, ToBase58};
|
||||||
|
@ -460,5 +461,56 @@ mod tests {
|
||||||
"xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
|
"xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
|
||||||
"xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt");
|
"xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn generate_sequential_normal_children(bh: &mut Bencher) {
|
||||||
|
let seed = "000102030405060708090a0b0c0d0e0f".from_hex().unwrap();
|
||||||
|
let msk = ExtendedPrivKey::new_master(Bitcoin, seed.as_slice()).unwrap();
|
||||||
|
let mut i = 0;
|
||||||
|
bh.iter( || {
|
||||||
|
black_box(msk.ckd_priv(Normal(i)));
|
||||||
|
i += 1;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn generate_sequential_hardened_children(bh: &mut Bencher) {
|
||||||
|
let seed = "000102030405060708090a0b0c0d0e0f".from_hex().unwrap();
|
||||||
|
let msk = ExtendedPrivKey::new_master(Bitcoin, seed.as_slice()).unwrap();
|
||||||
|
let mut i = 0;
|
||||||
|
bh.iter( || {
|
||||||
|
black_box(msk.ckd_priv(Hardened(i)));
|
||||||
|
i += 1;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn generate_sequential_public_children(bh: &mut Bencher) {
|
||||||
|
let seed = "000102030405060708090a0b0c0d0e0f".from_hex().unwrap();
|
||||||
|
let msk = ExtendedPrivKey::new_master(Bitcoin, seed.as_slice()).unwrap();
|
||||||
|
let mpk = ExtendedPubKey::from_private(&msk);
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
bh.iter( || {
|
||||||
|
black_box(mpk.ckd_pub(Normal(i)));
|
||||||
|
i += 1;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn generate_sequential_public_child_addresses(bh: &mut Bencher) {
|
||||||
|
use wallet::address::Address;
|
||||||
|
|
||||||
|
let seed = "000102030405060708090a0b0c0d0e0f".from_hex().unwrap();
|
||||||
|
let msk = ExtendedPrivKey::new_master(Bitcoin, seed.as_slice()).unwrap();
|
||||||
|
let mpk = ExtendedPubKey::from_private(&msk);
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
bh.iter( || {
|
||||||
|
let epk = mpk.ckd_pub(Normal(i)).unwrap();
|
||||||
|
black_box(Address::from_key(Bitcoin, &epk.public_key));
|
||||||
|
i += 1;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue