Merge pull request #388 from pandoracore/hashtypes-fns
Hash functions for public keys and scripts
This commit is contained in:
commit
71bf8d7bcf
|
@ -275,6 +275,16 @@ impl Script {
|
||||||
.into_script()
|
.into_script()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns 160-bit hash of the script
|
||||||
|
pub fn script_hash(&self) -> ScriptHash {
|
||||||
|
ScriptHash::hash(&self.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns 256-bit hash of the script for P2WSH outputs
|
||||||
|
pub fn wscript_hash(&self) -> WScriptHash {
|
||||||
|
WScriptHash::hash(&self.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
/// The length in bytes of the script
|
/// The length in bytes of the script
|
||||||
pub fn len(&self) -> usize { self.0.len() }
|
pub fn len(&self) -> usize { self.0.len() }
|
||||||
|
|
||||||
|
@ -292,13 +302,13 @@ impl Script {
|
||||||
|
|
||||||
/// Compute the P2SH output corresponding to this redeem script
|
/// Compute the P2SH output corresponding to this redeem script
|
||||||
pub fn to_p2sh(&self) -> Script {
|
pub fn to_p2sh(&self) -> Script {
|
||||||
Script::new_p2sh(&ScriptHash::hash(&self.0))
|
Script::new_p2sh(&self.script_hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the P2WSH output corresponding to this witnessScript (aka the "witness redeem
|
/// Compute the P2WSH output corresponding to this witnessScript (aka the "witness redeem
|
||||||
/// script")
|
/// script")
|
||||||
pub fn to_v0_p2wsh(&self) -> Script {
|
pub fn to_v0_p2wsh(&self) -> Script {
|
||||||
Script::new_v0_wsh(&WScriptHash::hash(&self.0))
|
Script::new_v0_wsh(&self.wscript_hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether a script pubkey is a p2sh output
|
/// Checks whether a script pubkey is a p2sh output
|
||||||
|
@ -1011,6 +1021,13 @@ mod test {
|
||||||
assert!(read_scriptint(&build_scriptint(-(1 << 31))).is_err());
|
assert!(read_scriptint(&build_scriptint(-(1 << 31))).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn script_hashes() {
|
||||||
|
let script = hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac");
|
||||||
|
assert_eq!(script.script_hash().to_hex(), "8292bcfbef1884f73c813dfe9c82fd7e814291ea");
|
||||||
|
assert_eq!(script.wscript_hash().to_hex(), "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn provably_unspendable_test() {
|
fn provably_unspendable_test() {
|
||||||
// p2pk
|
// p2pk
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
use consensus::encode::{Encodable, Decodable, Error};
|
use consensus::encode::{Encodable, Decodable, Error};
|
||||||
use hashes::{Hash, sha256, sha256d, ripemd160, hash160};
|
use hashes::{Hash, sha256, sha256d, ripemd160, hash160};
|
||||||
use hashes::hex::{FromHex, ToHex};
|
use hashes::hex::{FromHex, ToHex};
|
||||||
|
use util::key::PublicKey;
|
||||||
|
|
||||||
macro_rules! impl_hashencode {
|
macro_rules! impl_hashencode {
|
||||||
($hashtype:ident) => {
|
($hashtype:ident) => {
|
||||||
|
|
|
@ -22,6 +22,8 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use secp256k1::{self, Secp256k1};
|
use secp256k1::{self, Secp256k1};
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
|
use hashes::{Hash, hash160};
|
||||||
|
use hash_types::{PubkeyHash, WPubkeyHash};
|
||||||
use util::base58;
|
use util::base58;
|
||||||
|
|
||||||
/// A key-related error.
|
/// A key-related error.
|
||||||
|
@ -80,6 +82,28 @@ pub struct PublicKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PublicKey {
|
impl PublicKey {
|
||||||
|
/// Returns bitcoin 160-bit hash of the public key
|
||||||
|
pub fn pubkey_hash(&self) -> PubkeyHash {
|
||||||
|
if self.compressed {
|
||||||
|
PubkeyHash::hash(&self.key.serialize())
|
||||||
|
} else {
|
||||||
|
PubkeyHash::hash(&self.key.serialize_uncompressed())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns bitcoin 160-bit hash of the public key for witness program
|
||||||
|
pub fn wpubkey_hash(&self) -> Option<WPubkeyHash> {
|
||||||
|
if self.compressed {
|
||||||
|
Some(WPubkeyHash::from_inner(
|
||||||
|
hash160::Hash::hash(&self.key.serialize()).into_inner()
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
// We can't create witness pubkey hashes for an uncompressed
|
||||||
|
// public keys
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Write the public key into a writer
|
/// Write the public key into a writer
|
||||||
pub fn write_into<W: io::Write>(&self, mut writer: W) {
|
pub fn write_into<W: io::Write>(&self, mut writer: W) {
|
||||||
let write_res: io::Result<()> = if self.compressed {
|
let write_res: io::Result<()> = if self.compressed {
|
||||||
|
@ -360,6 +384,7 @@ mod tests {
|
||||||
use super::{PrivateKey, PublicKey};
|
use super::{PrivateKey, PublicKey};
|
||||||
use secp256k1::Secp256k1;
|
use secp256k1::Secp256k1;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use hashes::hex::ToHex;
|
||||||
use network::constants::Network::Testnet;
|
use network::constants::Network::Testnet;
|
||||||
use network::constants::Network::Bitcoin;
|
use network::constants::Network::Bitcoin;
|
||||||
use util::address::Address;
|
use util::address::Address;
|
||||||
|
@ -400,6 +425,22 @@ mod tests {
|
||||||
assert_eq!(pk, PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap());
|
assert_eq!(pk, PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pubkey_hash() {
|
||||||
|
let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
|
||||||
|
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
|
||||||
|
assert_eq!(pk.pubkey_hash().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
||||||
|
assert_eq!(upk.pubkey_hash().to_hex(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wpubkey_hash() {
|
||||||
|
let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
|
||||||
|
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
|
||||||
|
assert_eq!(pk.wpubkey_hash().unwrap().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
||||||
|
assert_eq!(upk.wpubkey_hash(), None);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_key_serde() {
|
fn test_key_serde() {
|
||||||
|
|
Loading…
Reference in New Issue