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
|
||||
/// 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> {
|
||||
|
||||
// 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()
|
||||
};
|
||||
|
||||
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.
|
||||
|
@ -1678,7 +1678,6 @@ impl Script {
|
|||
mut trace: Option<&mut Vec<TraceIteration>>)
|
||||
-> Result<(), ScriptError> {
|
||||
let &Script(ref raw) = self;
|
||||
let secp = Secp256k1::new();
|
||||
|
||||
let mut codeseparator_index = 0u;
|
||||
let mut exec_stack = vec![];
|
||||
|
@ -1916,7 +1915,7 @@ impl Script {
|
|||
// Otherwise unwrap it
|
||||
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)),
|
||||
_ => stack.push(Slice(SCRIPT_FALSE)),
|
||||
}
|
||||
|
@ -1977,7 +1976,7 @@ impl Script {
|
|||
// Try to validate the signature with the given key
|
||||
(Some(k), Some(s)) => {
|
||||
// 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() {
|
||||
sig = sig_iter.next();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ extern crate rand;
|
|||
extern crate rustrt;
|
||||
extern crate serialize;
|
||||
extern crate sync;
|
||||
extern crate test;
|
||||
extern crate time;
|
||||
|
||||
extern crate secp256k1 = "bitcoin-secp256k1-rs";
|
||||
|
|
|
@ -25,7 +25,8 @@ use std::hash;
|
|||
use serialize::json::{mod, ToJson};
|
||||
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha2;
|
||||
use crypto::sha2::Sha256;
|
||||
use crypto::ripemd160::Ripemd160;
|
||||
|
||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder};
|
||||
|
@ -130,6 +131,19 @@ impl Default for 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 {
|
||||
#[inline]
|
||||
fn default() -> Sha256dHash { Sha256dHash([0u8, ..32]) }
|
||||
|
@ -139,7 +153,7 @@ impl Sha256dHash {
|
|||
/// Create a hash by hashing some data
|
||||
pub fn from_data(data: &[u8]) -> Sha256dHash {
|
||||
let Sha256dHash(mut ret): Sha256dHash = Default::default();
|
||||
let mut sha2 = sha2::Sha256::new();
|
||||
let mut sha2 = Sha256::new();
|
||||
sha2.input(data);
|
||||
sha2.result(ret.as_mut_slice());
|
||||
sha2.reset();
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
//! 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 util::hash::Ripemd160Hash;
|
||||
use util::base58::{Base58Error,
|
||||
|
@ -29,6 +35,31 @@ pub struct Address {
|
|||
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 {
|
||||
fn base58_layout(&self) -> Vec<u8> {
|
||||
let mut ret = vec![
|
||||
|
@ -68,6 +99,9 @@ impl ::std::fmt::Show for Address {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serialize::hex::FromHex;
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
use secp256k1::Secp256k1;
|
||||
|
||||
use network::constants::Bitcoin;
|
||||
use util::hash::Ripemd160Hash;
|
||||
|
@ -84,5 +118,42 @@ mod tests {
|
|||
assert_eq!(addr.to_base58check().as_slice(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM");
|
||||
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)]
|
||||
mod tests {
|
||||
use serialize::hex::FromHex;
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
use network::constants::{Network, Bitcoin};
|
||||
use util::base58::{FromBase58, ToBase58};
|
||||
|
@ -460,5 +461,56 @@ mod tests {
|
|||
"xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
|
||||
"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