Merge rust-bitcoin/rust-bitcoin#1260: Create `crypto` module

2df51dae15 Create crypto module (Tobin C. Harding)

Pull request description:

  Done as part of [util flattening](https://github.com/rust-bitcoin/rust-bitcoin/issues/639).

  Create a `crypto` module and move into it (out of `util`):
  - ecdsa
  - schnorr
  - key

  After review, this PR now includes some type re-names
  - EcdsaSig -> ecdsa::Signature
  - SchnorrSig -> schnorr::Signature
  - EcdsaSigError -> ecdsa::Error
  - SchnorrSigError -> schnorr::Error
  - InvalidSchnorrSigSize -> InvalidSignatureSize  (this is an error enum variant)

ACKs for top commit:
  apoelstra:
    ACK 2df51dae15
  sanket1729:
    ACK 2df51dae15

Tree-SHA512: 7cf63d51ed5fdc737cd59767d9bb96b1e3501634e3aee855493f6a51ad5c5397ce4b25c77f9929abd70d6ceb351fc6520e835da108f4c9a46df5b9c2b52ca6b3
This commit is contained in:
Andrew Poelstra 2022-11-29 15:23:17 +00:00
commit 9266b1bbe0
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
17 changed files with 115 additions and 108 deletions

View File

@ -83,18 +83,18 @@ use bitcoin::consensus::encode;
use bitcoin::constants::COIN_VALUE; use bitcoin::constants::COIN_VALUE;
use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::hex::FromHex;
use bitcoin::hashes::Hash; use bitcoin::hashes::Hash;
use bitcoin::key::XOnlyPublicKey;
use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP}; use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP};
use bitcoin::psbt::serialize::Serialize; use bitcoin::psbt::serialize::Serialize;
use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType}; use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType};
use bitcoin::schnorr::TapTweak; use bitcoin::schnorr::{self, TapTweak};
use bitcoin::secp256k1::{Message, Secp256k1}; use bitcoin::secp256k1::{Message, Secp256k1};
use bitcoin::sighash::{self, SchnorrSighashType, SighashCache}; use bitcoin::sighash::{self, SchnorrSighashType, SighashCache};
use bitcoin::util::taproot::{ use bitcoin::util::taproot::{
LeafVersion, TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo, LeafVersion, TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo,
}; };
use bitcoin::{ use bitcoin::{
absolute, script, Address, Amount, OutPoint, SchnorrSig, Script, Transaction, TxIn, TxOut, absolute, script, Address, Amount, OutPoint, Script, Transaction, TxIn, TxOut, Txid, Witness,
Txid, Witness, XOnlyPublicKey,
}; };
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
@ -734,7 +734,7 @@ fn sign_psbt_schnorr(
let sig = secp.sign_schnorr(&Message::from_slice(&hash.into_inner()[..]).unwrap(), &keypair); let sig = secp.sign_schnorr(&Message::from_slice(&hash.into_inner()[..]).unwrap(), &keypair);
let final_signature = SchnorrSig { sig, hash_ty }; let final_signature = schnorr::Signature { sig, hash_ty };
if let Some(lh) = leaf_hash { if let Some(lh) = leaf_hash {
psbt_input.tap_script_sigs.insert((pubkey, lh), final_signature); psbt_input.tap_script_sigs.insert((pubkey, lh), final_signature);

View File

@ -43,14 +43,14 @@ use crate::blockdata::constants::{
use crate::blockdata::opcodes::all::*; use crate::blockdata::opcodes::all::*;
use crate::blockdata::script::Instruction; use crate::blockdata::script::Instruction;
use crate::blockdata::{opcodes, script}; use crate::blockdata::{opcodes, script};
use crate::crypto::key::PublicKey;
use crate::crypto::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
use crate::error::ParseIntError; use crate::error::ParseIntError;
use crate::hash_types::{PubkeyHash, ScriptHash}; use crate::hash_types::{PubkeyHash, ScriptHash};
use crate::hashes::{sha256, Hash, HashEngine}; use crate::hashes::{sha256, Hash, HashEngine};
use crate::network::constants::Network; use crate::network::constants::Network;
use crate::prelude::*; use crate::prelude::*;
use crate::util::base58; use crate::util::base58;
use crate::util::key::PublicKey;
use crate::util::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
use crate::util::taproot::TapBranchHash; use crate::util::taproot::TapBranchHash;
/// Address error. /// Address error.
@ -883,10 +883,10 @@ mod tests {
use secp256k1::XOnlyPublicKey; use secp256k1::XOnlyPublicKey;
use super::*; use super::*;
use crate::crypto::key::PublicKey;
use crate::hashes::hex::{FromHex, ToHex}; use crate::hashes::hex::{FromHex, ToHex};
use crate::internal_macros::{hex, hex_into, hex_script}; use crate::internal_macros::{hex, hex_into, hex_script};
use crate::network::constants::Network::{Bitcoin, Testnet}; use crate::network::constants::Network::{Bitcoin, Testnet};
use crate::util::key::PublicKey;
fn roundtrips(addr: &Address) { fn roundtrips(addr: &Address) {
assert_eq!( assert_eq!(

View File

@ -18,14 +18,14 @@ use secp256k1::{self, Secp256k1, XOnlyPublicKey};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde; use serde;
use crate::crypto::key::{self, KeyPair, PrivateKey, PublicKey};
use crate::hash_types::XpubIdentifier; use crate::hash_types::XpubIdentifier;
use crate::hashes::{hex, sha512, Hash, HashEngine, Hmac, HmacEngine}; use crate::hashes::{hex, sha512, Hash, HashEngine, Hmac, HmacEngine};
use crate::internal_macros::impl_bytes_newtype; use crate::internal_macros::impl_bytes_newtype;
use crate::io::Write; use crate::io::Write;
use crate::network::constants::Network; use crate::network::constants::Network;
use crate::prelude::*; use crate::prelude::*;
use crate::util::key::{KeyPair, PrivateKey, PublicKey}; use crate::util::base58;
use crate::util::{base58, key};
/// A chain code /// A chain code
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]

View File

@ -34,11 +34,11 @@ use crate::policy::DUST_RELAY_TX_FEE;
#[cfg(feature="bitcoinconsensus")] use core::convert::From; #[cfg(feature="bitcoinconsensus")] use core::convert::From;
use crate::OutPoint; use crate::OutPoint;
use crate::util::key::PublicKey; use crate::crypto::key::PublicKey;
use crate::address::WitnessVersion; use crate::address::WitnessVersion;
use crate::util::taproot::{LeafVersion, TapBranchHash, TapLeafHash}; use crate::util::taproot::{LeafVersion, TapBranchHash, TapLeafHash};
use secp256k1::{Secp256k1, Verification, XOnlyPublicKey}; use secp256k1::{Secp256k1, Verification, XOnlyPublicKey};
use crate::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey}; use crate::crypto::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
/// Bitcoin script. /// Bitcoin script.
/// ///
@ -1182,7 +1182,7 @@ mod test {
use crate::hashes::hex::{FromHex, ToHex}; use crate::hashes::hex::{FromHex, ToHex};
use crate::consensus::encode::{deserialize, serialize}; use crate::consensus::encode::{deserialize, serialize};
use crate::blockdata::opcodes; use crate::blockdata::opcodes;
use crate::util::key::PublicKey; use crate::crypto::key::PublicKey;
use crate::psbt::serialize::Serialize; use crate::psbt::serialize::Serialize;
use crate::internal_macros::hex_script; use crate::internal_macros::hex_script;

View File

@ -19,31 +19,31 @@ use crate::sighash::{EcdsaSighashType, NonStandardSighashType};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
pub struct EcdsaSig { pub struct Signature {
/// The underlying ECDSA Signature /// The underlying ECDSA Signature
pub sig: secp256k1::ecdsa::Signature, pub sig: secp256k1::ecdsa::Signature,
/// The corresponding hash type /// The corresponding hash type
pub hash_ty: EcdsaSighashType, pub hash_ty: EcdsaSighashType,
} }
impl EcdsaSig { impl Signature {
/// Constructs an ECDSA bitcoin signature for [`EcdsaSighashType::All`]. /// Constructs an ECDSA bitcoin signature for [`EcdsaSighashType::All`].
pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig { pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> Signature {
EcdsaSig { Signature {
sig, sig,
hash_ty: EcdsaSighashType::All hash_ty: EcdsaSighashType::All
} }
} }
/// Deserializes from slice following the standardness rules for [`EcdsaSighashType`]. /// Deserializes from slice following the standardness rules for [`EcdsaSighashType`].
pub fn from_slice(sl: &[u8]) -> Result<Self, EcdsaSigError> { pub fn from_slice(sl: &[u8]) -> Result<Self, Error> {
let (hash_ty, sig) = sl.split_last() let (hash_ty, sig) = sl.split_last()
.ok_or(EcdsaSigError::EmptySignature)?; .ok_or(Error::EmptySignature)?;
let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32) let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32)
.map_err(|_| EcdsaSigError::NonStandardSighashType(*hash_ty as u32))?; .map_err(|_| Error::NonStandardSighashType(*hash_ty as u32))?;
let sig = secp256k1::ecdsa::Signature::from_der(sig) let sig = secp256k1::ecdsa::Signature::from_der(sig)
.map_err(EcdsaSigError::Secp256k1)?; .map_err(Error::Secp256k1)?;
Ok(EcdsaSig { sig, hash_ty }) Ok(Signature { sig, hash_ty })
} }
/// Serializes an ECDSA signature (inner secp256k1 signature in DER format). /// Serializes an ECDSA signature (inner secp256k1 signature in DER format).
@ -56,21 +56,21 @@ impl EcdsaSig {
} }
} }
impl fmt::Display for EcdsaSig { impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
hex::format_hex(&self.sig.serialize_der(), f)?; hex::format_hex(&self.sig.serialize_der(), f)?;
hex::format_hex(&[self.hash_ty as u8], f) hex::format_hex(&[self.hash_ty as u8], f)
} }
} }
impl FromStr for EcdsaSig { impl FromStr for Signature {
type Err = EcdsaSigError; type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let bytes = Vec::from_hex(s)?; let bytes = Vec::from_hex(s)?;
let (sighash_byte, signature) = bytes.split_last() let (sighash_byte, signature) = bytes.split_last()
.ok_or(EcdsaSigError::EmptySignature)?; .ok_or(Error::EmptySignature)?;
Ok(EcdsaSig { Ok(Signature {
sig: secp256k1::ecdsa::Signature::from_der(signature)?, sig: secp256k1::ecdsa::Signature::from_der(signature)?,
hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)? hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)?
}) })
@ -80,7 +80,7 @@ impl FromStr for EcdsaSig {
/// A key-related error. /// A key-related error.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive] #[non_exhaustive]
pub enum EcdsaSigError { pub enum Error {
/// Hex encoding error /// Hex encoding error
HexEncoding(hex::Error), HexEncoding(hex::Error),
/// Base58 encoding error /// Base58 encoding error
@ -92,16 +92,16 @@ pub enum EcdsaSigError {
} }
impl fmt::Display for EcdsaSigError { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
EcdsaSigError::HexEncoding(ref e) => Error::HexEncoding(ref e) =>
write_err!(f, "EcdsaSig hex encoding error"; e), write_err!(f, "Signature hex encoding error"; e),
EcdsaSigError::NonStandardSighashType(hash_ty) => Error::NonStandardSighashType(hash_ty) =>
write!(f, "Non standard signature hash type {}", hash_ty), write!(f, "Non standard signature hash type {}", hash_ty),
EcdsaSigError::EmptySignature => Error::EmptySignature =>
write!(f, "Empty ECDSA signature"), write!(f, "Empty ECDSA signature"),
EcdsaSigError::Secp256k1(ref e) => Error::Secp256k1(ref e) =>
write_err!(f, "invalid ECDSA signature"; e), write_err!(f, "invalid ECDSA signature"; e),
} }
} }
@ -109,9 +109,9 @@ impl fmt::Display for EcdsaSigError {
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for EcdsaSigError { impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use self::EcdsaSigError::*; use self::Error::*;
match self { match self {
HexEncoding(e) => Some(e), HexEncoding(e) => Some(e),
@ -121,20 +121,20 @@ impl std::error::Error for EcdsaSigError {
} }
} }
impl From<secp256k1::Error> for EcdsaSigError { impl From<secp256k1::Error> for Error {
fn from(e: secp256k1::Error) -> EcdsaSigError { fn from(e: secp256k1::Error) -> Error {
EcdsaSigError::Secp256k1(e) Error::Secp256k1(e)
} }
} }
impl From<NonStandardSighashType> for EcdsaSigError { impl From<NonStandardSighashType> for Error {
fn from(err: NonStandardSighashType) -> Self { fn from(err: NonStandardSighashType) -> Self {
EcdsaSigError::NonStandardSighashType(err.0) Error::NonStandardSighashType(err.0)
} }
} }
impl From<hex::Error> for EcdsaSigError { impl From<hex::Error> for Error {
fn from(err: hex::Error) -> Self { fn from(err: hex::Error) -> Self {
EcdsaSigError::HexEncoding(err) Error::HexEncoding(err)
} }
} }

11
bitcoin/src/crypto/mod.rs Normal file
View File

@ -0,0 +1,11 @@
// Rust Bitcoin Library - Written by the rust-bitcoin developers.
// SPDX-License-Identifier: CC0-1.0
//! Cryptography
//!
//! Cryptography related functionality: keys and signatures.
//!
pub mod ecdsa;
pub mod key;
pub mod schnorr;

View File

@ -196,38 +196,38 @@ impl From<TweakedKeyPair> for KeyPair {
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
pub struct SchnorrSig { pub struct Signature {
/// The underlying schnorr signature /// The underlying schnorr signature
pub sig: secp256k1::schnorr::Signature, pub sig: secp256k1::schnorr::Signature,
/// The corresponding hash type /// The corresponding hash type
pub hash_ty: SchnorrSighashType, pub hash_ty: SchnorrSighashType,
} }
impl SchnorrSig { impl Signature {
/// Deserialize from slice /// Deserialize from slice
pub fn from_slice(sl: &[u8]) -> Result<Self, SchnorrSigError> { pub fn from_slice(sl: &[u8]) -> Result<Self, Error> {
match sl.len() { match sl.len() {
64 => { 64 => {
// default type // default type
let sig = secp256k1::schnorr::Signature::from_slice(sl) let sig = secp256k1::schnorr::Signature::from_slice(sl)
.map_err(SchnorrSigError::Secp256k1)?; .map_err(Error::Secp256k1)?;
Ok(SchnorrSig { sig, hash_ty: SchnorrSighashType::Default }) Ok(Signature { sig, hash_ty: SchnorrSighashType::Default })
}, },
65 => { 65 => {
let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65"); let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65");
let hash_ty = SchnorrSighashType::from_consensus_u8(*hash_ty) let hash_ty = SchnorrSighashType::from_consensus_u8(*hash_ty)
.map_err(|_| SchnorrSigError::InvalidSighashType(*hash_ty))?; .map_err(|_| Error::InvalidSighashType(*hash_ty))?;
let sig = secp256k1::schnorr::Signature::from_slice(sig) let sig = secp256k1::schnorr::Signature::from_slice(sig)
.map_err(SchnorrSigError::Secp256k1)?; .map_err(Error::Secp256k1)?;
Ok(SchnorrSig { sig, hash_ty }) Ok(Signature { sig, hash_ty })
} }
len => { len => {
Err(SchnorrSigError::InvalidSchnorrSigSize(len)) Err(Error::InvalidSignatureSize(len))
} }
} }
} }
/// Serialize SchnorrSig /// Serialize Signature
pub fn to_vec(self) -> Vec<u8> { pub fn to_vec(self) -> Vec<u8> {
// TODO: add support to serialize to a writer to SerializedSig // TODO: add support to serialize to a writer to SerializedSig
let mut ser_sig = self.sig.as_ref().to_vec(); let mut ser_sig = self.sig.as_ref().to_vec();
@ -244,24 +244,24 @@ impl SchnorrSig {
/// A schnorr sig related error. /// A schnorr sig related error.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive] #[non_exhaustive]
pub enum SchnorrSigError { pub enum Error {
/// Base58 encoding error /// Base58 encoding error
InvalidSighashType(u8), InvalidSighashType(u8),
/// Signature has valid size but does not parse correctly /// Signature has valid size but does not parse correctly
Secp256k1(secp256k1::Error), Secp256k1(secp256k1::Error),
/// Invalid schnorr signature size /// Invalid schnorr signature size
InvalidSchnorrSigSize(usize), InvalidSignatureSize(usize),
} }
impl fmt::Display for SchnorrSigError { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
SchnorrSigError::InvalidSighashType(hash_ty) => Error::InvalidSighashType(hash_ty) =>
write!(f, "Invalid signature hash type {}", hash_ty), write!(f, "Invalid signature hash type {}", hash_ty),
SchnorrSigError::Secp256k1(ref e) => Error::Secp256k1(ref e) =>
write_err!(f, "Schnorr signature has correct len but is malformed"; e), write_err!(f, "Schnorr signature has correct len but is malformed"; e),
SchnorrSigError::InvalidSchnorrSigSize(sz) => Error::InvalidSignatureSize(sz) =>
write!(f, "Invalid Schnorr signature size: {}", sz), write!(f, "Invalid Schnorr signature size: {}", sz),
} }
} }
@ -269,20 +269,20 @@ impl fmt::Display for SchnorrSigError {
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for SchnorrSigError { impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use self::SchnorrSigError::*; use self::Error::*;
match self { match self {
Secp256k1(e) => Some(e), Secp256k1(e) => Some(e),
InvalidSighashType(_) | InvalidSchnorrSigSize(_) => None, InvalidSighashType(_) | InvalidSignatureSize(_) => None,
} }
} }
} }
impl From<secp256k1::Error> for SchnorrSigError { impl From<secp256k1::Error> for Error {
fn from(e: secp256k1::Error) -> SchnorrSigError { fn from(e: secp256k1::Error) -> Error {
SchnorrSigError::Secp256k1(e) Error::Secp256k1(e)
} }
} }

View File

@ -97,6 +97,7 @@ pub mod bip158;
pub mod bip32; pub mod bip32;
pub mod blockdata; pub mod blockdata;
pub mod consensus; pub mod consensus;
pub mod crypto;
pub mod error; pub mod error;
pub mod hash_types; pub mod hash_types;
pub mod merkle_tree; pub mod merkle_tree;
@ -122,14 +123,13 @@ pub use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, T
pub use crate::blockdata::witness::{self, Witness}; pub use crate::blockdata::witness::{self, Witness};
pub use crate::blockdata::{constants, opcodes}; pub use crate::blockdata::{constants, opcodes};
pub use crate::consensus::encode::VarInt; pub use crate::consensus::encode::VarInt;
pub use crate::crypto::key::{self, PrivateKey, PublicKey};
pub use crate::crypto::{ecdsa, schnorr};
pub use crate::error::Error; pub use crate::error::Error;
pub use crate::hash_types::*; pub use crate::hash_types::*;
pub use crate::merkle_tree::MerkleBlock; pub use crate::merkle_tree::MerkleBlock;
pub use crate::network::constants::Network; pub use crate::network::constants::Network;
pub use crate::pow::{CompactTarget, Target, Work}; pub use crate::pow::{CompactTarget, Target, Work};
pub use crate::util::ecdsa::{self, EcdsaSig, EcdsaSigError};
pub use crate::util::key::{KeyPair, PrivateKey, PublicKey, XOnlyPublicKey};
pub use crate::util::schnorr::{self, SchnorrSig, SchnorrSigError};
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
mod io_extras { mod io_extras {

View File

@ -13,15 +13,16 @@ use crate::blockdata::script::Script;
use crate::blockdata::witness::Witness; use crate::blockdata::witness::Witness;
use crate::blockdata::transaction::{Transaction, TxOut}; use crate::blockdata::transaction::{Transaction, TxOut};
use crate::consensus::encode; use crate::consensus::encode;
use crate::crypto::{ecdsa, schnorr};
use crate::crypto::key::PublicKey;
use crate::hashes::{self, hash160, ripemd160, sha256, sha256d}; use crate::hashes::{self, hash160, ripemd160, sha256, sha256d};
use crate::bip32::KeySource; use crate::bip32::KeySource;
use crate::psbt::map::Map; use crate::psbt::map::Map;
use crate::psbt::serialize::Deserialize; use crate::psbt::serialize::Deserialize;
use crate::psbt::{self, error, raw, Error}; use crate::psbt::{self, error, raw, Error};
use crate::util::key::PublicKey;
use crate::sighash::{NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, SchnorrSighashType}; use crate::sighash::{NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, SchnorrSighashType};
use crate::util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash}; use crate::util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
use crate::{sighash, EcdsaSig, SchnorrSig}; use crate::sighash;
/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00 /// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00; const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
@ -80,7 +81,7 @@ pub struct Input {
pub witness_utxo: Option<TxOut>, pub witness_utxo: Option<TxOut>,
/// A map from public keys to their corresponding signature as would be /// A map from public keys to their corresponding signature as would be
/// pushed to the stack from a scriptSig or witness for a non-taproot inputs. /// pushed to the stack from a scriptSig or witness for a non-taproot inputs.
pub partial_sigs: BTreeMap<PublicKey, EcdsaSig>, pub partial_sigs: BTreeMap<PublicKey, ecdsa::Signature>,
/// The sighash type to be used for this input. Signatures for this input /// The sighash type to be used for this input. Signatures for this input
/// must use the sighash type. /// must use the sighash type.
pub sighash_type: Option<PsbtSighashType>, pub sighash_type: Option<PsbtSighashType>,
@ -112,10 +113,10 @@ pub struct Input {
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>, pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
/// Serialized schnorr signature with sighash type for key spend. /// Serialized schnorr signature with sighash type for key spend.
pub tap_key_sig: Option<SchnorrSig>, pub tap_key_sig: Option<schnorr::Signature>,
/// Map of `<xonlypubkey>|<leafhash>` with signature. /// Map of `<xonlypubkey>|<leafhash>` with signature.
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), SchnorrSig>, pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), schnorr::Signature>,
/// Map of Control blocks to Script version pair. /// Map of Control blocks to Script version pair.
#[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
pub tap_scripts: BTreeMap<ControlBlock, (Script, LeafVersion)>, pub tap_scripts: BTreeMap<ControlBlock, (Script, LeafVersion)>,
@ -267,7 +268,7 @@ impl Input {
} }
PSBT_IN_PARTIAL_SIG => { PSBT_IN_PARTIAL_SIG => {
impl_psbt_insert_pair! { impl_psbt_insert_pair! {
self.partial_sigs <= <raw_key: PublicKey>|<raw_value: EcdsaSig> self.partial_sigs <= <raw_key: PublicKey>|<raw_value: ecdsa::Signature>
} }
} }
PSBT_IN_SIGHASH_TYPE => { PSBT_IN_SIGHASH_TYPE => {
@ -314,12 +315,12 @@ impl Input {
} }
PSBT_IN_TAP_KEY_SIG => { PSBT_IN_TAP_KEY_SIG => {
impl_psbt_insert_pair! { impl_psbt_insert_pair! {
self.tap_key_sig <= <raw_key: _>|<raw_value: SchnorrSig> self.tap_key_sig <= <raw_key: _>|<raw_value: schnorr::Signature>
} }
} }
PSBT_IN_TAP_SCRIPT_SIG => { PSBT_IN_TAP_SCRIPT_SIG => {
impl_psbt_insert_pair! { impl_psbt_insert_pair! {
self.tap_script_sigs <= <raw_key: (XOnlyPublicKey, TapLeafHash)>|<raw_value: SchnorrSig> self.tap_script_sigs <= <raw_key: (XOnlyPublicKey, TapLeafHash)>|<raw_value: schnorr::Signature>
} }
} }
PSBT_IN_TAP_LEAF_SCRIPT => { PSBT_IN_TAP_LEAF_SCRIPT => {

View File

@ -23,8 +23,8 @@ use crate::blockdata::script::Script;
use crate::blockdata::transaction::{Transaction, TxOut}; use crate::blockdata::transaction::{Transaction, TxOut};
use crate::consensus::{encode, Encodable, Decodable}; use crate::consensus::{encode, Encodable, Decodable};
use crate::bip32::{self, ExtendedPrivKey, ExtendedPubKey, KeySource}; use crate::bip32::{self, ExtendedPrivKey, ExtendedPubKey, KeySource};
use crate::util::ecdsa::{EcdsaSig, EcdsaSigError}; use crate::crypto::ecdsa;
use crate::util::key::{PublicKey, PrivateKey}; use crate::crypto::key::{PublicKey, PrivateKey};
use crate::sighash::{self, EcdsaSighashType, SighashCache}; use crate::sighash::{self, EcdsaSighashType, SighashCache};
pub use crate::sighash::Prevouts; pub use crate::sighash::Prevouts;
@ -293,7 +293,7 @@ impl PartiallySignedTransaction {
Ok((msg, sighash_ty)) => (msg, sighash_ty), Ok((msg, sighash_ty)) => (msg, sighash_ty),
}; };
let sig = EcdsaSig { let sig = ecdsa::Signature {
sig: secp.sign_ecdsa(&msg, &sk.inner), sig: secp.sign_ecdsa(&msg, &sk.inner),
hash_ty: sighash_ty, hash_ty: sighash_ty,
}; };
@ -651,7 +651,7 @@ pub enum SigningAlgorithm {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub enum SignError { pub enum SignError {
/// An ECDSA key-related error occurred. /// An ECDSA key-related error occurred.
EcdsaSig(EcdsaSigError), EcdsaSig(ecdsa::Error),
/// Input index out of bounds (actual index, maximum index allowed). /// Input index out of bounds (actual index, maximum index allowed).
IndexOutOfBounds(usize, usize), IndexOutOfBounds(usize, usize),
/// Invalid Sighash type. /// Invalid Sighash type.
@ -740,8 +740,8 @@ impl From<sighash::Error> for SignError {
} }
} }
impl From<EcdsaSigError> for SignError { impl From<ecdsa::Error> for SignError {
fn from(e: EcdsaSigError) -> Self { fn from(e: ecdsa::Error) -> Self {
SignError::EcdsaSig(e) SignError::EcdsaSig(e)
} }
} }

View File

@ -17,11 +17,10 @@ use crate::consensus::encode::{self, serialize, Decodable, Encodable, deserializ
use secp256k1::{self, XOnlyPublicKey}; use secp256k1::{self, XOnlyPublicKey};
use crate::bip32::{ChildNumber, Fingerprint, KeySource}; use crate::bip32::{ChildNumber, Fingerprint, KeySource};
use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
use crate::util::ecdsa::{EcdsaSig, EcdsaSigError}; use crate::crypto::{ecdsa, schnorr};
use crate::psbt; use crate::psbt;
use crate::util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion}; use crate::util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion};
use crate::schnorr; use crate::crypto::key::PublicKey;
use crate::util::key::PublicKey;
use super::map::{TapTree, PsbtSighashType}; use super::map::{TapTree, PsbtSighashType};
@ -92,13 +91,13 @@ impl Deserialize for secp256k1::PublicKey {
} }
} }
impl Serialize for EcdsaSig { impl Serialize for ecdsa::Signature {
fn serialize(&self) -> Vec<u8> { fn serialize(&self) -> Vec<u8> {
self.to_vec() self.to_vec()
} }
} }
impl Deserialize for EcdsaSig { impl Deserialize for ecdsa::Signature {
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> { fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
// NB: Since BIP-174 says "the signature as would be pushed to the stack from // NB: Since BIP-174 says "the signature as would be pushed to the stack from
// a scriptSig or witness" we should ideally use a consensus deserialization and do // a scriptSig or witness" we should ideally use a consensus deserialization and do
@ -113,18 +112,18 @@ impl Deserialize for EcdsaSig {
// also has a field sighash_u32 (See BIP141). For example, when signing with non-standard // also has a field sighash_u32 (See BIP141). For example, when signing with non-standard
// 0x05, the sighash message would have the last field as 0x05u32 while, the verification // 0x05, the sighash message would have the last field as 0x05u32 while, the verification
// would use check the signature assuming sighash_u32 as `0x01`. // would use check the signature assuming sighash_u32 as `0x01`.
EcdsaSig::from_slice(bytes) ecdsa::Signature::from_slice(bytes)
.map_err(|e| match e { .map_err(|e| match e {
EcdsaSigError::EmptySignature => { ecdsa::Error::EmptySignature => {
encode::Error::ParseFailed("Empty partial signature data") encode::Error::ParseFailed("Empty partial signature data")
} }
EcdsaSigError::NonStandardSighashType(flag) => { ecdsa::Error::NonStandardSighashType(flag) => {
encode::Error::from(psbt::Error::NonStandardSighashType(flag)) encode::Error::from(psbt::Error::NonStandardSighashType(flag))
} }
EcdsaSigError::Secp256k1(..) => { ecdsa::Error::Secp256k1(..) => {
encode::Error::ParseFailed("Invalid Ecdsa signature") encode::Error::ParseFailed("Invalid Ecdsa signature")
} }
EcdsaSigError::HexEncoding(..) => { ecdsa::Error::HexEncoding(..) => {
unreachable!("Decoding from slice, not hex") unreachable!("Decoding from slice, not hex")
} }
}) })
@ -206,23 +205,23 @@ impl Deserialize for XOnlyPublicKey {
} }
} }
impl Serialize for schnorr::SchnorrSig { impl Serialize for schnorr::Signature {
fn serialize(&self) -> Vec<u8> { fn serialize(&self) -> Vec<u8> {
self.to_vec() self.to_vec()
} }
} }
impl Deserialize for schnorr::SchnorrSig { impl Deserialize for schnorr::Signature {
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> { fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
schnorr::SchnorrSig::from_slice(bytes) schnorr::Signature::from_slice(bytes)
.map_err(|e| match e { .map_err(|e| match e {
schnorr::SchnorrSigError::InvalidSighashType(flag) => { schnorr::Error::InvalidSighashType(flag) => {
encode::Error::from(psbt::Error::NonStandardSighashType(flag as u32)) encode::Error::from(psbt::Error::NonStandardSighashType(flag as u32))
} }
schnorr::SchnorrSigError::InvalidSchnorrSigSize(_) => { schnorr::Error::InvalidSignatureSize(_) => {
encode::Error::ParseFailed("Invalid Schnorr signature length") encode::Error::ParseFailed("Invalid Schnorr signature length")
} }
schnorr::SchnorrSigError::Secp256k1(..) => { schnorr::Error::Secp256k1(..) => {
encode::Error::ParseFailed("Invalid Schnorr signature") encode::Error::ParseFailed("Invalid Schnorr signature")
} }
}) })

View File

@ -1057,17 +1057,16 @@ mod tests {
use secp256k1::{self, SecretKey, XOnlyPublicKey}; use secp256k1::{self, SecretKey, XOnlyPublicKey};
use super::*; use super::*;
use crate::address::Address;
use crate::blockdata::locktime::absolute; use crate::blockdata::locktime::absolute;
use crate::consensus::deserialize; use crate::consensus::deserialize;
use crate::crypto::key::PublicKey;
use crate::hash_types::Sighash; use crate::hash_types::Sighash;
use crate::hashes::hex::{FromHex, ToHex}; use crate::hashes::hex::{FromHex, ToHex};
use crate::hashes::{Hash, HashEngine}; use crate::hashes::{Hash, HashEngine};
use crate::internal_macros::{hex_decode, hex_from_slice, hex_into, hex_script}; use crate::internal_macros::{hex_decode, hex_from_slice, hex_into, hex_script};
use crate::network::constants::Network; use crate::network::constants::Network;
use crate::sighash::{Annex, Error, Prevouts, ScriptPath, SighashCache};
use crate::util::key::PublicKey;
use crate::util::taproot::{TapBranchHash, TapLeafHash, TapSighashHash, TapTweakHash}; use crate::util::taproot::{TapBranchHash, TapLeafHash, TapSighashHash, TapTweakHash};
use crate::{Address, Script, Transaction, TxIn, TxOut};
extern crate serde_json; extern crate serde_json;

View File

@ -25,10 +25,10 @@ mod message_signing {
use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; use secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
use crate::address::{Address, AddressType}; use crate::address::{Address, AddressType};
use crate::crypto::key::PublicKey;
use crate::hashes::sha256d; use crate::hashes::sha256d;
#[cfg(feature = "base64")] #[cfg(feature = "base64")]
use crate::prelude::*; use crate::prelude::*;
use crate::util::key::PublicKey;
/// An error used for dealing with Bitcoin Signed Messages. /// An error used for dealing with Bitcoin Signed Messages.
#[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))] #[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))]
@ -267,7 +267,7 @@ mod tests {
fn test_incorrect_message_signature() { fn test_incorrect_message_signature() {
use secp256k1; use secp256k1;
use crate::util::key::PublicKey; use crate::crypto::key::PublicKey;
use crate::{Address, Network}; use crate::{Address, Network};
let secp = secp256k1::Secp256k1::new(); let secp = secp256k1::Secp256k1::new();

View File

@ -6,9 +6,6 @@
//! Functions needed by all parts of the Bitcoin library. //! Functions needed by all parts of the Bitcoin library.
//! //!
pub mod key;
pub mod ecdsa;
pub mod schnorr;
pub mod base58; pub mod base58;
pub mod taproot; pub mod taproot;

View File

@ -15,8 +15,7 @@ use core::fmt;
use core::cmp::Reverse; use core::cmp::Reverse;
use crate::hashes::{sha256, sha256t_hash_newtype, Hash, HashEngine}; use crate::hashes::{sha256, sha256t_hash_newtype, Hash, HashEngine};
use crate::schnorr::{TweakedPublicKey, UntweakedPublicKey, TapTweak}; use crate::crypto::schnorr::{TweakedPublicKey, UntweakedPublicKey, TapTweak, XOnlyPublicKey};
use crate::util::key::XOnlyPublicKey;
use crate::Script; use crate::Script;
use crate::consensus::Encodable; use crate::consensus::Encodable;
@ -1145,7 +1144,7 @@ impl std::error::Error for TaprootError {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::{Address, Network}; use crate::{Address, Network};
use crate::schnorr::TapTweak; use crate::crypto::schnorr::TapTweak;
use super::*; use super::*;
use crate::hashes::hex::{FromHex, ToHex}; use crate::hashes::hex::{FromHex, ToHex};

View File

@ -2,6 +2,7 @@
ignore = [ ignore = [
"bitcoin/src/blockdata", "bitcoin/src/blockdata",
"bitcoin/src/consensus", "bitcoin/src/consensus",
"bitcoin/src/crypto",
"bitcoin/src/psbt", "bitcoin/src/psbt",
"bitcoin/src/util", "bitcoin/src/util",
"hashes", "hashes",