Skip to content

Commit

Permalink
Re-org keys and ecdsa mods - pt.1
Browse files Browse the repository at this point in the history
This commit tries to achieve separation of signature- and key-related types, previously mixed in a single ECDSA module.

Rationale: bitcoin key types are not specific for signature algorithm.

This is achieved through
- Remove key mod with its content moved to ecdsa mod
- Re-export keys under key module in util mod - to make git generate diff for the rename of ecdsa mod in the next commit correctly.
  • Loading branch information
dr-orlovsky committed Jan 14, 2022
1 parent 2d9de78 commit b917016
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 96 deletions.
4 changes: 2 additions & 2 deletions src/blockdata/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use policy::DUST_RELAY_TX_FEE;
#[cfg(feature="bitcoinconsensus")] use core::convert::From;
#[cfg(feature="bitcoinconsensus")] use OutPoint;

use util::ecdsa::PublicKey;
use util::key::PublicKey;
use util::address::WitnessVersion;
use util::taproot::{LeafVersion, TapBranchHash, TapLeafHash};
use secp256k1::{Secp256k1, Verification};
Expand Down Expand Up @@ -1031,7 +1031,7 @@ mod test {
use hashes::hex::{FromHex, ToHex};
use consensus::encode::{deserialize, serialize};
use blockdata::opcodes;
use util::ecdsa::PublicKey;
use util::key::PublicKey;
use util::psbt::serialize::Serialize;

#[test]
Expand Down
20 changes: 10 additions & 10 deletions src/util/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
//! ```rust
//! use bitcoin::network::constants::Network;
//! use bitcoin::util::address::Address;
//! use bitcoin::util::ecdsa;
//! use bitcoin::PublicKey;
//! use bitcoin::secp256k1::Secp256k1;
//! use bitcoin::secp256k1::rand::thread_rng;
//!
//! // Generate random key pair.
//! let s = Secp256k1::new();
//! let public_key = ecdsa::PublicKey::new(s.generate_keypair(&mut thread_rng()).1);
//! let public_key = PublicKey::new(s.generate_keypair(&mut thread_rng()).1);
//!
//! // Generate pay-to-pubkey-hash address.
//! let address = Address::p2pkh(&public_key, Network::Bitcoin);
Expand All @@ -47,8 +47,8 @@ use blockdata::{script, opcodes};
use blockdata::constants::{PUBKEY_ADDRESS_PREFIX_MAIN, SCRIPT_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST, SCRIPT_ADDRESS_PREFIX_TEST, MAX_SCRIPT_ELEMENT_SIZE};
use network::constants::Network;
use util::base58;
use util::ecdsa;
use util::taproot::TapBranchHash;
use util::key::PublicKey;
use blockdata::script::Instruction;
use util::schnorr::{TapTweak, UntweakedPublicKey, TweakedPublicKey};

Expand Down Expand Up @@ -408,7 +408,7 @@ impl Payload {

/// Creates a pay to (compressed) public key hash payload from a public key
#[inline]
pub fn p2pkh(pk: &ecdsa::PublicKey) -> Payload {
pub fn p2pkh(pk: &PublicKey) -> Payload {
Payload::PubkeyHash(pk.pubkey_hash())
}

Expand All @@ -422,15 +422,15 @@ impl Payload {
}

/// Create a witness pay to public key payload from a public key
pub fn p2wpkh(pk: &ecdsa::PublicKey) -> Result<Payload, Error> {
pub fn p2wpkh(pk: &PublicKey) -> Result<Payload, Error> {
Ok(Payload::WitnessProgram {
version: WitnessVersion::V0,
program: pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?.to_vec(),
})
}

/// Create a pay to script payload that embeds a witness pay to public key
pub fn p2shwpkh(pk: &ecdsa::PublicKey) -> Result<Payload, Error> {
pub fn p2shwpkh(pk: &PublicKey) -> Result<Payload, Error> {
let builder = script::Builder::new()
.push_int(0)
.push_slice(&pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?);
Expand Down Expand Up @@ -543,7 +543,7 @@ impl Address {
///
/// This is the preferred non-witness type address.
#[inline]
pub fn p2pkh(pk: &ecdsa::PublicKey, network: Network) -> Address {
pub fn p2pkh(pk: &PublicKey, network: Network) -> Address {
Address {
network,
payload: Payload::p2pkh(pk),
Expand All @@ -568,7 +568,7 @@ impl Address {
///
/// # Errors
/// Will only return an error if an uncompressed public key is provided.
pub fn p2wpkh(pk: &ecdsa::PublicKey, network: Network) -> Result<Address, Error> {
pub fn p2wpkh(pk: &PublicKey, network: Network) -> Result<Address, Error> {
Ok(Address {
network,
payload: Payload::p2wpkh(pk)?,
Expand All @@ -581,7 +581,7 @@ impl Address {
///
/// # Errors
/// Will only return an Error if an uncompressed public key is provided.
pub fn p2shwpkh(pk: &ecdsa::PublicKey, network: Network) -> Result<Address, Error> {
pub fn p2shwpkh(pk: &PublicKey, network: Network) -> Result<Address, Error> {
Ok(Address {
network,
payload: Payload::p2shwpkh(pk)?,
Expand Down Expand Up @@ -878,7 +878,7 @@ mod tests {

use blockdata::script::Script;
use network::constants::Network::{Bitcoin, Testnet};
use util::ecdsa::PublicKey;
use util::key::PublicKey;
use secp256k1::XOnlyPublicKey;

use super::*;
Expand Down
2 changes: 1 addition & 1 deletion src/util/bip143.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ mod tests {
use consensus::encode::deserialize;
use network::constants::Network;
use util::address::Address;
use util::ecdsa::PublicKey;
use util::key::PublicKey;
use hashes::hex::FromHex;

use super::*;
Expand Down
18 changes: 9 additions & 9 deletions src/util/bip32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

use prelude::*;

use io::Write;
use core::{fmt, str::FromStr, default::Default};
#[cfg(feature = "std")] use std::error;
#[cfg(feature = "serde")] use serde;
Expand All @@ -28,9 +29,8 @@ use hashes::{sha512, Hash, HashEngine, Hmac, HmacEngine};
use secp256k1::{self, Secp256k1, XOnlyPublicKey};

use network::constants::Network;
use util::{base58, endian};
use util::{key, ecdsa, schnorr};
use io::Write;
use util::{base58, endian, key};
use util::key::{PublicKey, PrivateKey, KeyPair};

/// A chain code
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -528,8 +528,8 @@ impl ExtendedPrivKey {
}

/// Constructs ECDSA compressed private key matching internal secret key representation.
pub fn to_priv(&self) -> ecdsa::PrivateKey {
ecdsa::PrivateKey {
pub fn to_priv(&self) -> PrivateKey {
PrivateKey {
compressed: true,
network: self.network,
inner: self.private_key
Expand All @@ -538,8 +538,8 @@ impl ExtendedPrivKey {

/// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal
/// secret key representation.
pub fn to_keypair<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> schnorr::KeyPair {
schnorr::KeyPair::from_seckey_slice(secp, &self.private_key[..]).expect("BIP32 internal private key representation is broken")
pub fn to_keypair<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> KeyPair {
KeyPair::from_seckey_slice(secp, &self.private_key[..]).expect("BIP32 internal private key representation is broken")
}

/// Attempts to derive an extended private key from a path.
Expand Down Expand Up @@ -660,8 +660,8 @@ impl ExtendedPubKey {
}

/// Constructs ECDSA compressed public key matching internal public key representation.
pub fn to_pub(&self) -> ecdsa::PublicKey {
ecdsa::PublicKey {
pub fn to_pub(&self) -> PublicKey {
PublicKey {
compressed: true,
inner: self.public_key
}
Expand Down
50 changes: 48 additions & 2 deletions src/util/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,70 @@
//!
//! This module provides ECDSA keys used in Bitcoin that can be roundtrip
//! (de)serialized.
//!

pub use secp256k1::{XOnlyPublicKey, KeyPair};

use prelude::*;

use core::{ops, str::FromStr};
use core::fmt::{self, Write as _fmtWrite};
use io;
#[cfg(feature = "std")] use std::error;

use secp256k1::{self, Secp256k1};
use network::constants::Network;
use hashes::{Hash, hash160, hex};
use hashes::hex::FromHex;
use hash_types::{PubkeyHash, WPubkeyHash};
use util::base58;
use util::key::Error;
use blockdata::transaction::{EcdsaSigHashType, NonStandardSigHashType};


/// A key-related error.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Error {
/// Base58 encoding error
Base58(base58::Error),
/// secp256k1-related error
Secp256k1(secp256k1::Error),
}


impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Base58(ref e) => write!(f, "Key base58 error: {}", e),
Error::Secp256k1(ref e) => write!(f, "Key secp256k1 error: {}", e),
}
}
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
Error::Base58(ref e) => Some(e),
Error::Secp256k1(ref e) => Some(e),
}
}
}

#[doc(hidden)]
impl From<base58::Error> for Error {
fn from(e: base58::Error) -> Error {
Error::Base58(e)
}
}

#[doc(hidden)]
impl From<secp256k1::Error> for Error {
fn from(e: secp256k1::Error) -> Error {
Error::Secp256k1(e)
}
}


/// A Bitcoin ECDSA public key
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PublicKey {
Expand Down
70 changes: 0 additions & 70 deletions src/util/key.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/util/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ mod message_signing {
use secp256k1;
use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};

use util::ecdsa::PublicKey;
use util::key::PublicKey;
use util::address::{Address, AddressType};

/// An error used for dealing with Bitcoin Signed Messages.
Expand Down
9 changes: 8 additions & 1 deletion src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
//!

pub mod ecdsa;
pub mod key;
pub mod schnorr;
pub mod address;
pub mod amount;
Expand All @@ -37,6 +36,14 @@ pub mod sighash;

pub(crate) mod endian;

pub mod key {
//! Bitcoin keys.
//!
//! This module provides keys used in Bitcoin that can be roundtrip (de)serialized.

pub use super::ecdsa::{XOnlyPublicKey, PublicKey, PrivateKey, KeyPair, Error};
}

use prelude::*;
use io;
use core::fmt;
Expand Down

0 comments on commit b917016

Please sign in to comment.