Merge pull request #113 from rust-bitcoin/2018-07-secp-0.10.0
update to secp256k1 0.10.0
This commit is contained in:
commit
84040caa70
|
@ -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" ]
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue