Re-org keys and ecdsa mods - pt.1

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.
This commit is contained in:
Dr Maxim Orlovsky 2022-01-08 13:59:43 +01:00
parent 2d9de78725
commit b9170162d5
8 changed files with 79 additions and 96 deletions

View File

@ -39,7 +39,7 @@ use policy::DUST_RELAY_TX_FEE;
#[cfg(feature="bitcoinconsensus")] use core::convert::From; #[cfg(feature="bitcoinconsensus")] use core::convert::From;
#[cfg(feature="bitcoinconsensus")] use OutPoint; #[cfg(feature="bitcoinconsensus")] use OutPoint;
use util::ecdsa::PublicKey; use util::key::PublicKey;
use util::address::WitnessVersion; use util::address::WitnessVersion;
use util::taproot::{LeafVersion, TapBranchHash, TapLeafHash}; use util::taproot::{LeafVersion, TapBranchHash, TapLeafHash};
use secp256k1::{Secp256k1, Verification}; use secp256k1::{Secp256k1, Verification};
@ -1031,7 +1031,7 @@ mod test {
use hashes::hex::{FromHex, ToHex}; use hashes::hex::{FromHex, ToHex};
use consensus::encode::{deserialize, serialize}; use consensus::encode::{deserialize, serialize};
use blockdata::opcodes; use blockdata::opcodes;
use util::ecdsa::PublicKey; use util::key::PublicKey;
use util::psbt::serialize::Serialize; use util::psbt::serialize::Serialize;
#[test] #[test]

View File

@ -20,13 +20,13 @@
//! ```rust //! ```rust
//! use bitcoin::network::constants::Network; //! use bitcoin::network::constants::Network;
//! use bitcoin::util::address::Address; //! use bitcoin::util::address::Address;
//! use bitcoin::util::ecdsa; //! use bitcoin::PublicKey;
//! use bitcoin::secp256k1::Secp256k1; //! use bitcoin::secp256k1::Secp256k1;
//! use bitcoin::secp256k1::rand::thread_rng; //! use bitcoin::secp256k1::rand::thread_rng;
//! //!
//! // Generate random key pair. //! // Generate random key pair.
//! let s = Secp256k1::new(); //! 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. //! // Generate pay-to-pubkey-hash address.
//! let address = Address::p2pkh(&public_key, Network::Bitcoin); //! let address = Address::p2pkh(&public_key, Network::Bitcoin);
@ -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 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 network::constants::Network;
use util::base58; use util::base58;
use util::ecdsa;
use util::taproot::TapBranchHash; use util::taproot::TapBranchHash;
use util::key::PublicKey;
use blockdata::script::Instruction; use blockdata::script::Instruction;
use util::schnorr::{TapTweak, UntweakedPublicKey, TweakedPublicKey}; use util::schnorr::{TapTweak, UntweakedPublicKey, TweakedPublicKey};
@ -408,7 +408,7 @@ impl Payload {
/// Creates a pay to (compressed) public key hash payload from a public key /// Creates a pay to (compressed) public key hash payload from a public key
#[inline] #[inline]
pub fn p2pkh(pk: &ecdsa::PublicKey) -> Payload { pub fn p2pkh(pk: &PublicKey) -> Payload {
Payload::PubkeyHash(pk.pubkey_hash()) Payload::PubkeyHash(pk.pubkey_hash())
} }
@ -422,7 +422,7 @@ impl Payload {
} }
/// Create a witness pay to public key payload from a public key /// 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 { Ok(Payload::WitnessProgram {
version: WitnessVersion::V0, version: WitnessVersion::V0,
program: pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?.to_vec(), program: pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?.to_vec(),
@ -430,7 +430,7 @@ impl Payload {
} }
/// Create a pay to script payload that embeds a witness pay to public key /// 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() let builder = script::Builder::new()
.push_int(0) .push_int(0)
.push_slice(&pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?); .push_slice(&pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?);
@ -543,7 +543,7 @@ impl Address {
/// ///
/// This is the preferred non-witness type address. /// This is the preferred non-witness type address.
#[inline] #[inline]
pub fn p2pkh(pk: &ecdsa::PublicKey, network: Network) -> Address { pub fn p2pkh(pk: &PublicKey, network: Network) -> Address {
Address { Address {
network, network,
payload: Payload::p2pkh(pk), payload: Payload::p2pkh(pk),
@ -568,7 +568,7 @@ impl Address {
/// ///
/// # Errors /// # Errors
/// Will only return an error if an uncompressed public key is provided. /// 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 { Ok(Address {
network, network,
payload: Payload::p2wpkh(pk)?, payload: Payload::p2wpkh(pk)?,
@ -581,7 +581,7 @@ impl Address {
/// ///
/// # Errors /// # Errors
/// Will only return an Error if an uncompressed public key is provided. /// 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 { Ok(Address {
network, network,
payload: Payload::p2shwpkh(pk)?, payload: Payload::p2shwpkh(pk)?,
@ -878,7 +878,7 @@ mod tests {
use blockdata::script::Script; use blockdata::script::Script;
use network::constants::Network::{Bitcoin, Testnet}; use network::constants::Network::{Bitcoin, Testnet};
use util::ecdsa::PublicKey; use util::key::PublicKey;
use secp256k1::XOnlyPublicKey; use secp256k1::XOnlyPublicKey;
use super::*; use super::*;

View File

@ -194,7 +194,7 @@ mod tests {
use consensus::encode::deserialize; use consensus::encode::deserialize;
use network::constants::Network; use network::constants::Network;
use util::address::Address; use util::address::Address;
use util::ecdsa::PublicKey; use util::key::PublicKey;
use hashes::hex::FromHex; use hashes::hex::FromHex;
use super::*; use super::*;

View File

@ -19,6 +19,7 @@
use prelude::*; use prelude::*;
use io::Write;
use core::{fmt, str::FromStr, default::Default}; use core::{fmt, str::FromStr, default::Default};
#[cfg(feature = "std")] use std::error; #[cfg(feature = "std")] use std::error;
#[cfg(feature = "serde")] use serde; #[cfg(feature = "serde")] use serde;
@ -28,9 +29,8 @@ use hashes::{sha512, Hash, HashEngine, Hmac, HmacEngine};
use secp256k1::{self, Secp256k1, XOnlyPublicKey}; use secp256k1::{self, Secp256k1, XOnlyPublicKey};
use network::constants::Network; use network::constants::Network;
use util::{base58, endian}; use util::{base58, endian, key};
use util::{key, ecdsa, schnorr}; use util::key::{PublicKey, PrivateKey, KeyPair};
use io::Write;
/// A chain code /// A chain code
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -528,8 +528,8 @@ impl ExtendedPrivKey {
} }
/// Constructs ECDSA compressed private key matching internal secret key representation. /// Constructs ECDSA compressed private key matching internal secret key representation.
pub fn to_priv(&self) -> ecdsa::PrivateKey { pub fn to_priv(&self) -> PrivateKey {
ecdsa::PrivateKey { PrivateKey {
compressed: true, compressed: true,
network: self.network, network: self.network,
inner: self.private_key inner: self.private_key
@ -538,8 +538,8 @@ impl ExtendedPrivKey {
/// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal /// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal
/// secret key representation. /// secret key representation.
pub fn to_keypair<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> schnorr::KeyPair { pub fn to_keypair<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> KeyPair {
schnorr::KeyPair::from_seckey_slice(secp, &self.private_key[..]).expect("BIP32 internal private key representation is broken") 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. /// Attempts to derive an extended private key from a path.
@ -660,8 +660,8 @@ impl ExtendedPubKey {
} }
/// Constructs ECDSA compressed public key matching internal public key representation. /// Constructs ECDSA compressed public key matching internal public key representation.
pub fn to_pub(&self) -> ecdsa::PublicKey { pub fn to_pub(&self) -> PublicKey {
ecdsa::PublicKey { PublicKey {
compressed: true, compressed: true,
inner: self.public_key inner: self.public_key
} }

View File

@ -15,13 +15,15 @@
//! //!
//! This module provides ECDSA keys used in Bitcoin that can be roundtrip //! This module provides ECDSA keys used in Bitcoin that can be roundtrip
//! (de)serialized. //! (de)serialized.
//!
pub use secp256k1::{XOnlyPublicKey, KeyPair};
use prelude::*; use prelude::*;
use core::{ops, str::FromStr}; use core::{ops, str::FromStr};
use core::fmt::{self, Write as _fmtWrite}; use core::fmt::{self, Write as _fmtWrite};
use io; use io;
#[cfg(feature = "std")] use std::error;
use secp256k1::{self, Secp256k1}; use secp256k1::{self, Secp256k1};
use network::constants::Network; use network::constants::Network;
@ -29,10 +31,54 @@ use hashes::{Hash, hash160, hex};
use hashes::hex::FromHex; use hashes::hex::FromHex;
use hash_types::{PubkeyHash, WPubkeyHash}; use hash_types::{PubkeyHash, WPubkeyHash};
use util::base58; use util::base58;
use util::key::Error;
use blockdata::transaction::{EcdsaSigHashType, NonStandardSigHashType}; 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 /// A Bitcoin ECDSA public key
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PublicKey { pub struct PublicKey {

View File

@ -1,70 +0,0 @@
// Rust Bitcoin Library
// Written in 2014 by
// Andrew Poelstra <apoelstra@wpsoftware.net>
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//
//! Bitcoin keys.
//!
//! This module provides keys used in Bitcoin that can be roundtrip (de)serialized.
//!
pub use util::ecdsa::{PrivateKey, PublicKey};
pub use secp256k1::{XOnlyPublicKey, KeyPair};
use core::fmt;
#[cfg(feature = "std")] use std::error;
use secp256k1;
use util::base58;
/// 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)
}
}

View File

@ -42,7 +42,7 @@ mod message_signing {
use secp256k1; use secp256k1;
use secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
use util::ecdsa::PublicKey; use util::key::PublicKey;
use util::address::{Address, AddressType}; use util::address::{Address, AddressType};
/// An error used for dealing with Bitcoin Signed Messages. /// An error used for dealing with Bitcoin Signed Messages.

View File

@ -18,7 +18,6 @@
//! //!
pub mod ecdsa; pub mod ecdsa;
pub mod key;
pub mod schnorr; pub mod schnorr;
pub mod address; pub mod address;
pub mod amount; pub mod amount;
@ -37,6 +36,14 @@ pub mod sighash;
pub(crate) mod endian; 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 prelude::*;
use io; use io;
use core::fmt; use core::fmt;