diff --git a/src/key.rs b/src/key.rs index 6626181..6d081c3 100644 --- a/src/key.rs +++ b/src/key.rs @@ -7,6 +7,7 @@ use constants; use ffi; use super::{Result, InvalidNonce, InvalidPublicKey, InvalidSecretKey}; +use super::init; /// Secret 256-bit nonce used as `k` in an ECDSA signature pub struct Nonce([u8, ..constants::NONCE_SIZE]); @@ -124,20 +125,22 @@ impl PublicKey { ) } - /// Creates a new public key from a secret key + /// Creates a new public key from a secret key. Marked `unsafe` since you must + /// call `init()` (or construct a `Secp256k1`, which does this for you) before + /// using this function #[inline] - pub fn from_secret_key(sk: &SecretKey, compressed: bool) -> PublicKey { + pub unsafe fn from_secret_key(sk: &SecretKey, compressed: bool) -> PublicKey { let mut pk = PublicKey::new(compressed); let compressed = if compressed {1} else {0}; - unsafe { - let mut len = 0; - while ffi::secp256k1_ecdsa_pubkey_create( - pk.as_mut_ptr(), &mut len, - sk.as_ptr(), compressed) != 1 { - // loop - } - assert_eq!(len as uint, pk.len()); - }; + let mut len = 0; + + while ffi::secp256k1_ecdsa_pubkey_create( + pk.as_mut_ptr(), &mut len, + sk.as_ptr(), compressed) != 1 { + // loop + } + assert_eq!(len as uint, pk.len()); + pk } diff --git a/src/secp256k1.rs b/src/secp256k1.rs index cc297a1..b30012b 100644 --- a/src/secp256k1.rs +++ b/src/secp256k1.rs @@ -25,7 +25,7 @@ extern crate libc; extern crate sync; -use std::io::IoError; +use std::io::{IoError, IoResult}; use std::rand::OsRng; use libc::c_int; use sync::one::{Once, ONCE_INIT}; @@ -84,28 +84,40 @@ pub struct Secp256k1 { rng: OsRng } +/// Does one-time initialization of the secp256k1 engine. Can be called +/// multiple times, and is called by the `Secp256k1` constructor. This +/// only needs to be called directly if you are using the library without +/// a `Secp256k1` object, e.g. batch key generation through +/// `key::PublicKey::from_secret_key`. +pub fn init() { + unsafe { + Secp256k1_init.doit(|| { + ffi::secp256k1_start(); + }); + } +} + impl Secp256k1 { /// Constructs a new secp256k1 engine. pub fn new() -> Result { - unsafe { - Secp256k1_init.doit(|| { - ffi::secp256k1_start(); - }); - } + init(); match OsRng::new() { Ok(rng) => Ok(Secp256k1 { rng: rng }), Err(e) => Err(RngError(e)) } } - /// Generates a randam keypair + /// Generates a random keypair. Convenience function for `key::SecretKey::new` + /// and `key::PublicKey::from_secret_key`; call those functions directly for + /// batch key generation. pub fn generate_keypair(&mut self, compressed: bool) -> (key::SecretKey, key::PublicKey) { let sk = key::SecretKey::new(&mut self.rng); - (sk, key::PublicKey::from_secret_key(&sk, compressed)) + unsafe { (sk, key::PublicKey::from_secret_key(&sk, compressed)) } } - /// Generates a random nonce + /// Generates a random nonce. Convenience function for `key::Nonce::new`; call + /// that function directly for batch nonce generation pub fn generate_nonce(&mut self) -> key::Nonce { key::Nonce::new(&mut self.rng) }