Merge pull request #113 from rust-bitcoin/2018-07-secp-0.10.0

update to secp256k1 0.10.0
This commit is contained in:
Andrew Poelstra 2018-08-20 16:05:09 +00:00 committed by GitHub
commit 84040caa70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 39 deletions

View File

@ -32,5 +32,5 @@ git = "https://github.com/KokaKiwi/rust-hex"
rev = "19fd37137686c30058bd9d11d21590e726ffdf31" rev = "19fd37137686c30058bd9d11d21590e726ffdf31"
[dependencies.secp256k1] [dependencies.secp256k1]
version = "0.9" version = "0.10"
features = [ "rand" ] features = [ "rand" ]

View File

@ -230,7 +230,7 @@ impl From<secp256k1::Error> for Error {
impl ExtendedPrivKey { impl ExtendedPrivKey {
/// Construct a new master key from a seed value /// Construct a new master key from a seed value
pub fn new_master(secp: &Secp256k1, network: Network, seed: &[u8]) -> Result<ExtendedPrivKey, Error> { pub fn new_master<C>(secp: &Secp256k1<C>, network: Network, seed: &[u8]) -> Result<ExtendedPrivKey, Error> {
let mut result = [0; 64]; let mut result = [0; 64];
let mut hmac = Hmac::new(Sha512::new(), b"Bitcoin seed"); let mut hmac = Hmac::new(Sha512::new(), b"Bitcoin seed");
hmac.input(seed); hmac.input(seed);
@ -247,9 +247,9 @@ impl ExtendedPrivKey {
} }
/// Attempts to derive an extended private key from a path. /// Attempts to derive an extended private key from a path.
pub fn derive_priv( pub fn derive_priv<C: secp256k1::Signing>(
&self, &self,
secp: &Secp256k1, secp: &Secp256k1<C>,
cnums: &[ChildNumber], cnums: &[ChildNumber],
) -> Result<ExtendedPrivKey, Error> { ) -> Result<ExtendedPrivKey, Error> {
let mut sk: ExtendedPrivKey = *self; let mut sk: ExtendedPrivKey = *self;
@ -260,14 +260,14 @@ impl ExtendedPrivKey {
} }
/// Private->Private child key derivation /// Private->Private child key derivation
pub fn ckd_priv(&self, secp: &Secp256k1, i: ChildNumber) -> Result<ExtendedPrivKey, Error> { pub fn ckd_priv<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Result<ExtendedPrivKey, Error> {
let mut result = [0; 64]; let mut result = [0; 64];
let mut hmac = Hmac::new(Sha512::new(), &self.chain_code[..]); let mut hmac = Hmac::new(Sha512::new(), &self.chain_code[..]);
let mut be_n = [0; 4]; let mut be_n = [0; 4];
match i { match i {
ChildNumber::Normal {..} => { ChildNumber::Normal {..} => {
// Non-hardened key: compute public data and use that // Non-hardened key: compute public data and use that
hmac.input(&PublicKey::from_secret_key(secp, &self.secret_key).unwrap().serialize()[..]); hmac.input(&PublicKey::from_secret_key(secp, &self.secret_key).serialize()[..]);
} }
ChildNumber::Hardened {..} => { ChildNumber::Hardened {..} => {
// Hardened key: use only secret data to prevent public derivation // Hardened key: use only secret data to prevent public derivation
@ -293,7 +293,7 @@ impl ExtendedPrivKey {
} }
/// Returns the HASH160 of the chaincode /// Returns the HASH160 of the chaincode
pub fn identifier(&self, secp: &Secp256k1) -> [u8; 20] { pub fn identifier<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> [u8; 20] {
let mut sha2_res = [0; 32]; let mut sha2_res = [0; 32];
let mut ripemd_res = [0; 20]; let mut ripemd_res = [0; 20];
// Compute extended public key // Compute extended public key
@ -311,28 +311,28 @@ impl ExtendedPrivKey {
} }
/// Returns the first four bytes of the identifier /// Returns the first four bytes of the identifier
pub fn fingerprint(&self, secp: &Secp256k1) -> Fingerprint { pub fn fingerprint<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> Fingerprint {
Fingerprint::from(&self.identifier(secp)[0..4]) Fingerprint::from(&self.identifier(secp)[0..4])
} }
} }
impl ExtendedPubKey { impl ExtendedPubKey {
/// Derives a public key from a private key /// Derives a public key from a private key
pub fn from_private(secp: &Secp256k1, sk: &ExtendedPrivKey) -> ExtendedPubKey { pub fn from_private<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &ExtendedPrivKey) -> ExtendedPubKey {
ExtendedPubKey { ExtendedPubKey {
network: sk.network, network: sk.network,
depth: sk.depth, depth: sk.depth,
parent_fingerprint: sk.parent_fingerprint, parent_fingerprint: sk.parent_fingerprint,
child_number: sk.child_number, child_number: sk.child_number,
public_key: PublicKey::from_secret_key(secp, &sk.secret_key).unwrap(), public_key: PublicKey::from_secret_key(secp, &sk.secret_key),
chain_code: sk.chain_code chain_code: sk.chain_code
} }
} }
/// Attempts to derive an extended public key from a path. /// Attempts to derive an extended public key from a path.
pub fn derive_pub( pub fn derive_pub<C: secp256k1::Verification>(
&self, &self,
secp: &Secp256k1, secp: &Secp256k1<C>,
cnums: &[ChildNumber], cnums: &[ChildNumber],
) -> Result<ExtendedPubKey, Error> { ) -> Result<ExtendedPubKey, Error> {
let mut pk: ExtendedPubKey = *self; let mut pk: ExtendedPubKey = *self;
@ -343,7 +343,7 @@ impl ExtendedPubKey {
} }
/// Compute the scalar tweak added to this key to get a child key /// Compute the scalar tweak added to this key to get a child key
pub fn ckd_pub_tweak(&self, secp: &Secp256k1, i: ChildNumber) -> Result<(SecretKey, ChainCode), Error> { pub fn ckd_pub_tweak<C>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Result<(SecretKey, ChainCode), Error> {
match i { match i {
ChildNumber::Hardened {..} => { ChildNumber::Hardened {..} => {
Err(Error::CannotDeriveFromHardenedKey) Err(Error::CannotDeriveFromHardenedKey)
@ -366,7 +366,11 @@ impl ExtendedPubKey {
} }
/// Public->Public child key derivation /// Public->Public child key derivation
pub fn ckd_pub(&self, secp: &Secp256k1, i: ChildNumber) -> Result<ExtendedPubKey, Error> { pub fn ckd_pub<C: secp256k1::Verification>(
&self,
secp: &Secp256k1<C>,
i: ChildNumber,
) -> Result<ExtendedPubKey, Error> {
let (sk, chain_code) = self.ckd_pub_tweak(secp, i)?; let (sk, chain_code) = self.ckd_pub_tweak(secp, i)?;
let mut pk = self.public_key.clone(); let mut pk = self.public_key.clone();
pk.add_exp_assign(secp, &sk).map_err(Error::Ecdsa)?; pk.add_exp_assign(secp, &sk).map_err(Error::Ecdsa)?;
@ -426,7 +430,7 @@ impl FromStr for ExtendedPrivKey {
type Err = base58::Error; type Err = base58::Error;
fn from_str(inp: &str) -> Result<ExtendedPrivKey, base58::Error> { fn from_str(inp: &str) -> Result<ExtendedPrivKey, base58::Error> {
let s = Secp256k1::with_caps(secp256k1::ContextFlag::None); let s = Secp256k1::without_caps();
let data = base58::from_check(inp)?; let data = base58::from_check(inp)?;
if data.len() != 78 { if data.len() != 78 {
@ -477,7 +481,7 @@ impl FromStr for ExtendedPubKey {
type Err = base58::Error; type Err = base58::Error;
fn from_str(inp: &str) -> Result<ExtendedPubKey, base58::Error> { fn from_str(inp: &str) -> Result<ExtendedPubKey, base58::Error> {
let s = Secp256k1::with_caps(secp256k1::ContextFlag::None); let s = Secp256k1::without_caps();
let data = base58::from_check(inp)?; let data = base58::from_check(inp)?;
if data.len() != 78 { if data.len() != 78 {
@ -511,7 +515,7 @@ mod tests {
use std::str::FromStr; use std::str::FromStr;
use std::string::ToString; use std::string::ToString;
use secp256k1::Secp256k1; use secp256k1::{self, Secp256k1};
use hex::decode as hex_decode; use hex::decode as hex_decode;
use network::constants::Network::{self, Bitcoin}; use network::constants::Network::{self, Bitcoin};
@ -520,7 +524,7 @@ mod tests {
use super::ChildNumber::{Hardened, Normal}; use super::ChildNumber::{Hardened, Normal};
use super::Error; use super::Error;
fn test_path(secp: &Secp256k1, fn test_path<C: secp256k1::Signing + secp256k1::Verification>(secp: &Secp256k1<C>,
network: Network, network: Network,
seed: &[u8], seed: &[u8],
path: &[ChildNumber], path: &[ChildNumber],

View File

@ -170,7 +170,7 @@ impl<'a> From<&'a [u8]> for Template {
} }
/// Tweak keys using some arbitrary data /// Tweak keys using some arbitrary data
pub fn tweak_keys(secp: &Secp256k1, keys: &[PublicKey], contract: &[u8]) -> Result<Vec<PublicKey>, Error> { pub fn tweak_keys<C: secp256k1::Verification>(secp: &Secp256k1<C>, keys: &[PublicKey], contract: &[u8]) -> Result<Vec<PublicKey>, Error> {
let mut ret = Vec::with_capacity(keys.len()); let mut ret = Vec::with_capacity(keys.len());
for mut key in keys.iter().cloned() { for mut key in keys.iter().cloned() {
let mut hmac_raw = [0; 32]; let mut hmac_raw = [0; 32];
@ -185,7 +185,7 @@ pub fn tweak_keys(secp: &Secp256k1, keys: &[PublicKey], contract: &[u8]) -> Resu
} }
/// Compute a tweak from some given data for the given public key /// Compute a tweak from some given data for the given public key
pub fn compute_tweak(secp: &Secp256k1, pk: &PublicKey, contract: &[u8]) -> Result<SecretKey, Error> { pub fn compute_tweak<C>(secp: &Secp256k1<C>, pk: &PublicKey, contract: &[u8]) -> Result<SecretKey, Error> {
let mut hmac_raw = [0; 32]; let mut hmac_raw = [0; 32];
let mut hmac = hmac::Hmac::new(sha2::Sha256::new(), &pk.serialize()); let mut hmac = hmac::Hmac::new(sha2::Sha256::new(), &pk.serialize());
hmac.input(contract); hmac.input(contract);
@ -194,9 +194,9 @@ pub fn compute_tweak(secp: &Secp256k1, pk: &PublicKey, contract: &[u8]) -> Resul
} }
/// Tweak a secret key using some arbitrary data (calls `compute_tweak` internally) /// Tweak a secret key using some arbitrary data (calls `compute_tweak` internally)
pub fn tweak_secret_key(secp: &Secp256k1, key: &SecretKey, contract: &[u8]) -> Result<SecretKey, Error> { pub fn tweak_secret_key<C: secp256k1::Signing>(secp: &Secp256k1<C>, key: &SecretKey, contract: &[u8]) -> Result<SecretKey, Error> {
// Compute public key // Compute public key
let pk = PublicKey::from_secret_key(secp, &key).map_err(Error::Secp)?; let pk = PublicKey::from_secret_key(secp, &key);
// Compute tweak // Compute tweak
let hmac_sk = compute_tweak(secp, &pk, contract)?; let hmac_sk = compute_tweak(secp, &pk, contract)?;
// Execute the tweak // Execute the tweak
@ -207,7 +207,7 @@ pub fn tweak_secret_key(secp: &Secp256k1, key: &SecretKey, contract: &[u8]) -> R
} }
/// Takes a contract, template and key set and runs through all the steps /// Takes a contract, template and key set and runs through all the steps
pub fn create_address(secp: &Secp256k1, pub fn create_address<C: secp256k1::Verification>(secp: &Secp256k1<C>,
network: Network, network: Network,
contract: &[u8], contract: &[u8],
keys: &[PublicKey], keys: &[PublicKey],
@ -343,9 +343,9 @@ mod tests {
#[test] #[test]
fn tweak_secret() { fn tweak_secret() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let (sk1, pk1) = secp.generate_keypair(&mut thread_rng()).unwrap(); let (sk1, pk1) = secp.generate_keypair(&mut thread_rng());
let (sk2, pk2) = secp.generate_keypair(&mut thread_rng()).unwrap(); let (sk2, pk2) = secp.generate_keypair(&mut thread_rng());
let (sk3, pk3) = secp.generate_keypair(&mut thread_rng()).unwrap(); let (sk3, pk3) = secp.generate_keypair(&mut thread_rng());
let pks = [pk1, pk2, pk3]; let pks = [pk1, pk2, pk3];
let contract = b"if bottle mt dont remembr drink wont pay"; let contract = b"if bottle mt dont remembr drink wont pay";
@ -353,9 +353,9 @@ mod tests {
// Directly compute tweaks on pubkeys // Directly compute tweaks on pubkeys
let tweaked_pks = tweak_keys(&secp, &pks, &contract[..]).unwrap(); let tweaked_pks = tweak_keys(&secp, &pks, &contract[..]).unwrap();
// Compute tweaks on secret keys // Compute tweaks on secret keys
let tweaked_pk1 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk1, &contract[..]).unwrap()).unwrap(); let tweaked_pk1 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk1, &contract[..]).unwrap());
let tweaked_pk2 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk2, &contract[..]).unwrap()).unwrap(); let tweaked_pk2 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk2, &contract[..]).unwrap());
let tweaked_pk3 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk3, &contract[..]).unwrap()).unwrap(); let tweaked_pk3 = PublicKey::from_secret_key(&secp, &tweak_secret_key(&secp, &sk3, &contract[..]).unwrap());
// Check equality // Check equality
assert_eq!(tweaked_pks[0], tweaked_pk1); assert_eq!(tweaked_pks[0], tweaked_pk1);
assert_eq!(tweaked_pks[1], tweaked_pk2); assert_eq!(tweaked_pks[1], tweaked_pk2);

View File

@ -17,7 +17,7 @@
//! //!
use std::str::FromStr; use std::str::FromStr;
use util::Error; use util::Error;
use secp256k1::Secp256k1; use secp256k1::{self, Secp256k1};
use secp256k1::key::{PublicKey, SecretKey}; use secp256k1::key::{PublicKey, SecretKey};
use util::address::Address; use util::address::Address;
use network::constants::Network; use network::constants::Network;
@ -46,24 +46,24 @@ impl Privkey {
} }
/// Computes the public key as supposed to be used with this secret /// Computes the public key as supposed to be used with this secret
pub fn public_key(&self, secp: &Secp256k1) -> Result<PublicKey, Error> { pub fn public_key<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> PublicKey {
Ok(PublicKey::from_secret_key(secp, &self.key)?) PublicKey::from_secret_key(secp, &self.key)
} }
/// Converts a private key to a segwit address /// Converts a private key to a segwit address
#[inline] #[inline]
pub fn to_address(&self, secp: &Secp256k1) -> Result<Address, Error> { pub fn to_address<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> Address {
Ok(Address::p2wpkh(&self.public_key(secp)?, self.network)) Address::p2wpkh(&self.public_key(secp), self.network)
} }
/// Converts a private key to a legacy (non-segwit) address /// Converts a private key to a legacy (non-segwit) address
#[inline] #[inline]
pub fn to_legacy_address(&self, secp: &Secp256k1) -> Result<Address, Error> { pub fn to_legacy_address<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> Address {
if self.compressed { if self.compressed {
Ok(Address::p2pkh(&self.public_key(secp)?, self.network)) Address::p2pkh(&self.public_key(secp), self.network)
} }
else { else {
Ok(Address::p2upkh(&self.public_key(secp)?, self.network)) Address::p2upkh(&self.public_key(secp), self.network)
} }
} }
@ -156,7 +156,7 @@ mod tests {
assert_eq!(&sk.to_string(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"); assert_eq!(&sk.to_string(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let pk = sk.to_legacy_address(&secp).unwrap(); let pk = sk.to_legacy_address(&secp);
assert_eq!(&pk.to_string(), "mqwpxxvfv3QbM8PU8uBx2jaNt9btQqvQNx"); assert_eq!(&pk.to_string(), "mqwpxxvfv3QbM8PU8uBx2jaNt9btQqvQNx");
// mainnet uncompressed // mainnet uncompressed
@ -166,7 +166,7 @@ mod tests {
assert_eq!(&sk.to_string(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3"); assert_eq!(&sk.to_string(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3");
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let pk = sk.to_legacy_address(&secp).unwrap(); let pk = sk.to_legacy_address(&secp);
assert_eq!(&pk.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8"); assert_eq!(&pk.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8");
} }
} }