use crate::hashes::{hash160, sha256, sha256d};
pub use bitcoin::{PubkeyHash, WPubkeyHash};
macro_rules! impl_hashencode {
($hashtype:ident) => {
impl $crate::encode::Encodable for $hashtype {
fn consensus_encode<W: std::io::Write>(
&self,
w: W,
) -> Result<usize, crate::encode::Error> {
self.as_byte_array().consensus_encode(w)
}
}
impl $crate::encode::Decodable for $hashtype {
fn consensus_decode<R: std::io::Read>(r: R) -> Result<Self, $crate::encode::Error> {
Ok(Self::from_byte_array(
<<$hashtype as $crate::hashes::Hash>::Bytes>::consensus_decode(r)?,
))
}
}
};
}
hashes::hash_newtype! {
pub struct Txid(pub(crate) sha256d::Hash);
pub struct Wtxid(pub(crate) sha256d::Hash);
pub struct BlockHash(pub(crate) sha256d::Hash);
pub struct Sighash(pub(crate) sha256d::Hash);
pub struct ScriptHash(pub(crate) hash160::Hash);
pub struct WScriptHash(pub(crate) sha256::Hash);
pub struct TxMerkleNode(sha256d::Hash);
}
hashes::impl_hex_for_newtype!(Txid, Wtxid, BlockHash, ScriptHash, WScriptHash, TxMerkleNode);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(Txid, Wtxid, BlockHash, ScriptHash, WScriptHash, TxMerkleNode);
hashes::impl_debug_only_for_newtype!(Sighash);
impl_hashencode!(Txid);
impl_hashencode!(Wtxid);
impl_hashencode!(Sighash);
impl_hashencode!(BlockHash);
impl_hashencode!(TxMerkleNode);
impl BlockHash {
pub const GENESIS_PREVIOUS_BLOCK_HASH: Self = Self::from_byte_array([0; 32]);
}
impl Txid {
pub const COINBASE_PREVOUT: Self = Self::from_byte_array([0; 32]);
}
impl ScriptHash {
pub fn hash_script(s: &crate::Script) -> Self {
Self(hash160::Hash::hash(s.as_bytes()))
}
}
impl WScriptHash {
pub fn hash_script(s: &crate::Script) -> Self {
Self(sha256::Hash::hash(s.as_bytes()))
}
}
#[cfg(test)]
#[cfg(feature = "serde")]
mod serde_tests {
use super::*;
use crate::{AssetEntropy, AssetId, ContractHash, DynafedRoot};
use crate::dynafed::{ElidedRoot, ParamsRoot};
const TEST_VECTOR: [u8; 32] = [
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44,
0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, 0x44,
];
const CBOR: [u8; 34] = [
0x58, 0x20,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44,
0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, 0x44,
];
const FORWARD_JSON: &str = "\"0102030405060708090a0b0c0d0e0f100000000011223344ffffffff11223344\"";
const REVERSED_JSON: &str = "\"44332211ffffffff4433221100000000100f0e0d0c0b0a090807060504030201\"";
macro_rules! serde_rtt_test32 {
($testname:ident, $ty:ty, $json:expr) => {
#[test]
fn $testname() {
let obj = <$ty>::from_byte_array(TEST_VECTOR);
let enc_json = serde_json::to_string(&obj).expect("encode json");
assert_eq!(
enc_json,
$json,
"encoded JSON did not match target '{}'", $json
);
let dec_json: $ty = serde_json::from_str(&enc_json).expect("decode json");
assert_eq!(
dec_json,
obj,
"decoded JSON did not match object '{}'", obj
);
let enc_cbor = serde_cbor::to_vec(&obj).expect("encode cbor");
assert_eq!(
enc_cbor,
CBOR,
"encoded CBOR did not match target '{:?}'", CBOR
);
let dec_cbor: $ty = serde_cbor::from_slice(&enc_cbor).expect("decode cbor");
assert_eq!(
dec_cbor,
obj,
"decoded CBOR did not match object '{}'", obj
);
let s = obj.to_string();
assert_eq!(
s,
$json[1..65],
"encoded string did not match target '{:?}'", $json
);
let dec_s: $ty = s.parse().expect("parsing string");
assert_eq!(
dec_s,
obj,
"decoded string did not match object '{}'", obj
);
}
}
}
serde_rtt_test32!(serde_rtt_txid, Txid, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_wtxid, Wtxid, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_blockhash, BlockHash, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_wscripthash, WScriptHash, FORWARD_JSON);
serde_rtt_test32!(serde_rtt_merklenode, TxMerkleNode, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_assetid, AssetId, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_contracthash, ContractHash, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_entropy, AssetEntropy, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_dynaroot, DynafedRoot, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_elidedroot, ElidedRoot, REVERSED_JSON);
serde_rtt_test32!(serde_rtt_paramsroot, ParamsRoot, REVERSED_JSON);
}