bitcoin-cash 1.0.0-beta.0

A library for creating and parsing Bitcoin Cash trasactions
Documentation
use crate::{
    error::Result, BitcoinByteArray, BitcoinCode, BitcoinDataType, ByteArray, DataType,
    FixedByteArray, Function, Op,
};

use serde::{Deserialize, Serialize};
use sha1::Digest;
use std::borrow::Cow;
use std::fmt::{Debug, Display};
use std::sync::Arc;

pub trait Hashed: Display + Debug + Sized + Eq + PartialEq {
    fn as_slice(&self) -> &[u8];
    fn from_slice(hash: &[u8]) -> Result<Self>;
    fn from_byte_array(hash: ByteArray) -> Result<Self>;
    fn function() -> Function;
    fn digest_slice(msg: &[u8]) -> Arc<[u8]>;
    fn digest(msg: impl Into<ByteArray>) -> Self {
        let msg = msg.into();
        let hash = Self::digest_slice(&msg);
        Self::from_byte_array(msg.apply_function(hash, Self::function()))
            .expect("Self::digest_slice produced invalid slice")
    }
    fn named(self, name: impl Into<Cow<'static, str>>) -> Self;
    fn from_hex_le(s: &str) -> Result<Self> {
        Self::from_slice(&hex::decode(s)?.iter().cloned().rev().collect::<Vec<_>>())
    }
    fn from_hex_be(s: &str) -> Result<Self> {
        Self::from_slice(&hex::decode(s)?)
    }
    fn from_slice_le(hash_le: &[u8]) -> Result<Self> {
        Self::from_slice(&hash_le.iter().cloned().rev().collect::<Vec<_>>())
    }
    fn to_vec_le(&self) -> Vec<u8> {
        self.as_slice().iter().cloned().rev().collect()
    }
    fn to_hex_le(&self) -> String {
        hex::encode(self.to_vec_le())
    }
    fn to_hex_be(&self) -> String {
        hex::encode(self.as_slice())
    }
    fn as_byte_array(&self) -> &ByteArray;
    fn into_byte_array(self) -> ByteArray;
    fn concat(self, other: impl Into<ByteArray>) -> ByteArray {
        self.into_byte_array().concat(other)
    }
}

#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
pub struct Sha1(FixedByteArray<[u8; 20]>);
#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
pub struct Ripemd160(FixedByteArray<[u8; 20]>);
#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
pub struct Sha256(FixedByteArray<[u8; 32]>);
#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
pub struct Sha256d(FixedByteArray<[u8; 32]>);
#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
pub struct Hash160(FixedByteArray<[u8; 20]>);

impl Sha1 {
    pub fn new(hash: [u8; 20]) -> Self {
        Sha1(FixedByteArray::new_unnamed(hash))
    }
}
impl Ripemd160 {
    pub fn new(hash: [u8; 20]) -> Self {
        Ripemd160(FixedByteArray::new_unnamed(hash))
    }
}
impl Sha256 {
    pub fn new(hash: [u8; 32]) -> Self {
        Sha256(FixedByteArray::new_unnamed(hash))
    }
}
impl Sha256d {
    pub fn new(hash: [u8; 32]) -> Self {
        Sha256d(FixedByteArray::new_unnamed(hash))
    }
}
impl Hash160 {
    pub fn new(hash: [u8; 20]) -> Self {
        Hash160(FixedByteArray::new_unnamed(hash))
    }
}

impl Debug for Sha1 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "Sha1({})", self.to_hex_le())
    }
}
impl Debug for Ripemd160 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "Ripemd160({})", self.to_hex_le())
    }
}
impl Debug for Sha256 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "Sha256({})", self.to_hex_le())
    }
}
impl Debug for Sha256d {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "Sha256d({})", self.to_hex_le())
    }
}
impl Debug for Hash160 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "Hash160({})", self.to_hex_le())
    }
}

impl Display for Sha1 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "{}", self.to_hex_le())
    }
}
impl Display for Ripemd160 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "{}", self.to_hex_le())
    }
}
impl Display for Sha256 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "{}", self.to_hex_le())
    }
}
impl Display for Sha256d {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "{}", self.to_hex_le())
    }
}
impl Display for Hash160 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(fmt, "{}", self.to_hex_le())
    }
}

impl Hashed for Sha1 {
    fn function() -> Function {
        Function::Sha1
    }
    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
        sha1::Sha1::digest(msg).as_slice().into()
    }
    fn as_slice(&self) -> &[u8] {
        self.0.as_ref()
    }
    fn from_slice(hash: &[u8]) -> Result<Self> {
        Ok(Sha1(FixedByteArray::from_slice_unnamed(hash)?))
    }
    fn from_byte_array(hash: ByteArray) -> Result<Self> {
        Ok(Sha1(FixedByteArray::from_byte_array(hash)?))
    }
    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
        Sha1(self.0.named(name))
    }
    fn as_byte_array(&self) -> &ByteArray {
        self.0.as_byte_array()
    }
    fn into_byte_array(self) -> ByteArray {
        self.0.into_byte_array()
    }
}

impl Hashed for Ripemd160 {
    fn function() -> Function {
        Function::Ripemd160
    }
    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
        ripemd160::Ripemd160::digest(msg).as_slice().into()
    }
    fn as_slice(&self) -> &[u8] {
        self.0.as_ref()
    }
    fn from_slice(hash: &[u8]) -> Result<Self> {
        Ok(Ripemd160(FixedByteArray::from_slice_unnamed(hash)?))
    }
    fn from_byte_array(hash: ByteArray) -> Result<Self> {
        Ok(Ripemd160(FixedByteArray::from_byte_array(hash)?))
    }
    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
        Ripemd160(self.0.named(name))
    }
    fn as_byte_array(&self) -> &ByteArray {
        self.0.as_byte_array()
    }
    fn into_byte_array(self) -> ByteArray {
        self.0.into_byte_array()
    }
}

impl Hashed for Sha256 {
    fn function() -> Function {
        Function::Sha256
    }
    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
        sha2::Sha256::digest(msg).as_slice().into()
    }
    fn as_slice(&self) -> &[u8] {
        self.0.as_ref()
    }
    fn from_slice(hash: &[u8]) -> Result<Self> {
        Ok(Sha256(FixedByteArray::from_slice_unnamed(hash)?))
    }
    fn from_byte_array(hash: ByteArray) -> Result<Self> {
        Ok(Sha256(FixedByteArray::from_byte_array(hash)?))
    }
    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
        Sha256(self.0.named(name))
    }
    fn as_byte_array(&self) -> &ByteArray {
        self.0.as_byte_array()
    }
    fn into_byte_array(self) -> ByteArray {
        self.0.into_byte_array()
    }
}

impl Hashed for Sha256d {
    fn function() -> Function {
        Function::Hash256
    }
    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
        sha2::Sha256::digest(sha2::Sha256::digest(msg).as_slice())
            .as_slice()
            .into()
    }
    fn as_slice(&self) -> &[u8] {
        self.0.as_ref()
    }
    fn from_slice(hash: &[u8]) -> Result<Self> {
        Ok(Sha256d(FixedByteArray::from_slice_unnamed(hash)?))
    }
    fn from_byte_array(hash: ByteArray) -> Result<Self> {
        Ok(Sha256d(FixedByteArray::from_byte_array(hash)?))
    }
    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
        Sha256d(self.0.named(name))
    }
    fn as_byte_array(&self) -> &ByteArray {
        self.0.as_byte_array()
    }
    fn into_byte_array(self) -> ByteArray {
        self.0.into_byte_array()
    }
}

impl Hashed for Hash160 {
    fn function() -> Function {
        Function::Hash160
    }
    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
        ripemd160::Ripemd160::digest(sha2::Sha256::digest(msg).as_slice())
            .as_slice()
            .into()
    }
    fn as_slice(&self) -> &[u8] {
        self.0.as_ref()
    }
    fn from_slice(hash: &[u8]) -> Result<Self> {
        Ok(Hash160(FixedByteArray::from_slice_unnamed(hash)?))
    }
    fn from_byte_array(hash: ByteArray) -> Result<Self> {
        Ok(Hash160(FixedByteArray::from_byte_array(hash)?))
    }
    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
        Hash160(self.0.named(name))
    }
    fn as_byte_array(&self) -> &ByteArray {
        self.0.as_byte_array()
    }
    fn into_byte_array(self) -> ByteArray {
        self.0.into_byte_array()
    }
}

impl BitcoinCode for Sha1 {
    fn ser(&self) -> ByteArray {
        self.0.ser()
    }

    fn deser(data: ByteArray) -> Result<(Self, ByteArray)> {
        let (array, leftover) = FixedByteArray::<[u8; 20]>::deser(data)?;
        Ok((Sha1(array), leftover))
    }
}

impl BitcoinCode for Ripemd160 {
    fn ser(&self) -> ByteArray {
        self.0.ser()
    }

    fn deser(data: ByteArray) -> Result<(Self, ByteArray)> {
        let (array, leftover) = FixedByteArray::<[u8; 20]>::deser(data)?;
        Ok((Ripemd160(array), leftover))
    }
}

impl BitcoinCode for Sha256 {
    fn ser(&self) -> ByteArray {
        self.0.ser()
    }

    fn deser(data: ByteArray) -> Result<(Self, ByteArray)> {
        let (array, leftover) = FixedByteArray::<[u8; 32]>::deser(data)?;
        Ok((Sha256(array), leftover))
    }
}

impl BitcoinCode for Sha256d {
    fn ser(&self) -> ByteArray {
        self.0.ser()
    }

    fn deser(data: ByteArray) -> Result<(Self, ByteArray)> {
        let (array, leftover) = FixedByteArray::<[u8; 32]>::deser(data)?;
        Ok((Sha256d(array), leftover))
    }
}

impl BitcoinCode for Hash160 {
    fn ser(&self) -> ByteArray {
        self.0.ser()
    }

    fn deser(data: ByteArray) -> Result<(Self, ByteArray)> {
        let (array, leftover) = FixedByteArray::<[u8; 20]>::deser(data)?;
        Ok((Hash160(array), leftover))
    }
}

impl BitcoinDataType for Sha1 {
    type Type = BitcoinByteArray;
    fn to_data(&self) -> Self::Type {
        BitcoinByteArray(self.as_byte_array().clone())
    }
    fn to_pushop(&self) -> Op {
        self.as_byte_array().clone().into()
    }
    fn to_data_type(&self) -> DataType {
        DataType::ByteArray(Some(self.0.len()))
    }
}

impl BitcoinDataType for Ripemd160 {
    type Type = BitcoinByteArray;
    fn to_data(&self) -> Self::Type {
        BitcoinByteArray(self.as_byte_array().clone())
    }
    fn to_pushop(&self) -> Op {
        self.as_byte_array().clone().into()
    }
    fn to_data_type(&self) -> DataType {
        DataType::ByteArray(Some(self.0.len()))
    }
}

impl BitcoinDataType for Sha256 {
    type Type = BitcoinByteArray;
    fn to_data(&self) -> Self::Type {
        BitcoinByteArray(self.as_byte_array().clone())
    }
    fn to_pushop(&self) -> Op {
        self.as_byte_array().clone().into()
    }
    fn to_data_type(&self) -> DataType {
        DataType::ByteArray(Some(self.0.len()))
    }
}

impl BitcoinDataType for Sha256d {
    type Type = BitcoinByteArray;
    fn to_data(&self) -> Self::Type {
        BitcoinByteArray(self.as_byte_array().clone())
    }
    fn to_pushop(&self) -> Op {
        self.as_byte_array().clone().into()
    }
    fn to_data_type(&self) -> DataType {
        DataType::ByteArray(Some(self.0.len()))
    }
}

impl BitcoinDataType for Hash160 {
    type Type = BitcoinByteArray;
    fn to_data(&self) -> Self::Type {
        BitcoinByteArray(self.as_byte_array().clone())
    }
    fn to_pushop(&self) -> Op {
        self.as_byte_array().clone().into()
    }
    fn to_data_type(&self) -> DataType {
        DataType::ByteArray(Some(self.0.len()))
    }
}

impl From<Sha1> for ByteArray {
    fn from(hash: Sha1) -> Self {
        hash.into_byte_array()
    }
}
impl From<Ripemd160> for ByteArray {
    fn from(hash: Ripemd160) -> Self {
        hash.into_byte_array()
    }
}
impl From<Sha256> for ByteArray {
    fn from(hash: Sha256) -> Self {
        hash.into_byte_array()
    }
}
impl From<Sha256d> for ByteArray {
    fn from(hash: Sha256d) -> Self {
        hash.into_byte_array()
    }
}
impl From<Hash160> for ByteArray {
    fn from(hash: Hash160) -> Self {
        hash.into_byte_array()
    }
}

#[cfg(test)]
mod tests {
    use super::{Hash160, Hashed, Result, Ripemd160, Sha1, Sha256, Sha256d};
    use crate::{error::Error, ByteArrayError};
    use hex_literal::hex;

    #[test]
    fn test_sha1_slice() -> Result<()> {
        const EMPTY_SHA1: [u8; 20] = hex!("da39a3ee5e6b4b0d3255bfef95601890afd80709");
        assert_eq!(Sha1::digest(b"").as_slice(), EMPTY_SHA1);
        assert_eq!(Sha1::digest(b""), Sha1::from_slice(&EMPTY_SHA1)?);
        assert_eq!(
            Error::ByteArrayError(ByteArrayError::InvalidSlice {
                expected: 20,
                actual: 2,
            })
            .to_string(),
            Sha1::from_slice(&[0, 0]).unwrap_err().to_string(),
        );
        Ok(())
    }

    #[test]
    fn test_sha1_hex_be() -> Result<()> {
        const EMPTY_SHA1: &str = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
        assert_eq!(Sha1::digest(b"").to_hex_be(), EMPTY_SHA1);
        assert_eq!(Sha1::digest(b""), Sha1::from_hex_be(EMPTY_SHA1)?);
        Ok(())
    }

    #[test]
    fn test_sha1_hex_le() -> Result<()> {
        const EMPTY_SHA1_LE: &str = "0907d8af90186095efbf55320d4b6b5eeea339da";
        assert_eq!(Sha1::digest(b"").to_hex_le(), EMPTY_SHA1_LE);
        assert_eq!(Sha1::digest(b""), Sha1::from_hex_le(EMPTY_SHA1_LE)?);
        Ok(())
    }

    #[test]
    fn test_ripemd160_slice() -> Result<()> {
        const EMPTY_RIPEMD: [u8; 20] = hex!("9c1185a5c5e9fc54612808977ee8f548b2258d31");
        assert_eq!(Ripemd160::digest(b"").as_slice(), EMPTY_RIPEMD);
        assert_eq!(
            Ripemd160::digest(b""),
            Ripemd160::from_slice(&EMPTY_RIPEMD)?
        );
        assert_eq!(
            Error::ByteArrayError(ByteArrayError::InvalidSlice {
                expected: 20,
                actual: 2,
            })
            .to_string(),
            Ripemd160::from_slice(&[0, 0]).unwrap_err().to_string(),
        );
        Ok(())
    }

    #[test]
    fn test_ripemd160_hex_be() -> Result<()> {
        const EMPTY_RIPEMD: &str = "9c1185a5c5e9fc54612808977ee8f548b2258d31";
        assert_eq!(Ripemd160::digest(b"").to_hex_be(), EMPTY_RIPEMD);
        assert_eq!(
            Ripemd160::digest(b""),
            Ripemd160::from_hex_be(EMPTY_RIPEMD)?
        );
        Ok(())
    }

    #[test]
    fn test_ripemd160_hex_le() -> Result<()> {
        const EMPTY_RIPEMD_LE: &str = "318d25b248f5e87e9708286154fce9c5a585119c";
        assert_eq!(Ripemd160::digest(b"").to_hex_le(), EMPTY_RIPEMD_LE);
        assert_eq!(
            Ripemd160::digest(b""),
            Ripemd160::from_hex_le(EMPTY_RIPEMD_LE)?
        );
        Ok(())
    }

    #[test]
    fn test_sha256_slice() -> Result<()> {
        const EMPTY_SHA256: [u8; 32] =
            hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
        assert_eq!(Sha256::digest(b"").as_slice(), EMPTY_SHA256);
        assert_eq!(Sha256::digest(b""), Sha256::from_slice(&EMPTY_SHA256)?);
        assert_eq!(
            Error::ByteArrayError(ByteArrayError::InvalidSlice {
                expected: 32,
                actual: 2,
            })
            .to_string(),
            Sha256::from_slice(&[0, 0]).unwrap_err().to_string(),
        );
        Ok(())
    }

    #[test]
    fn test_sha256_hex_be() -> Result<()> {
        const EMPTY_SHA256: &str =
            "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
        assert_eq!(Sha256::digest(b"").to_hex_be(), EMPTY_SHA256);
        assert_eq!(Sha256::digest(b""), Sha256::from_hex_be(EMPTY_SHA256)?);
        Ok(())
    }

    #[test]
    fn test_sha256_hex_le() -> Result<()> {
        const EMPTY_SHA256_LE: &str =
            "55b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3";
        assert_eq!(Sha256::digest(b"").to_hex_le(), EMPTY_SHA256_LE);
        assert_eq!(Sha256::digest(b""), Sha256::from_hex_le(EMPTY_SHA256_LE)?);
        Ok(())
    }

    #[test]
    fn test_sha256d_slice() -> Result<()> {
        const EMPTY_SHA256D: [u8; 32] =
            hex!("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456");
        assert_eq!(Sha256d::digest(b"").as_slice(), EMPTY_SHA256D);
        assert_eq!(Sha256d::digest(b""), Sha256d::from_slice(&EMPTY_SHA256D)?);
        assert_eq!(
            Error::ByteArrayError(ByteArrayError::InvalidSlice {
                expected: 32,
                actual: 2,
            })
            .to_string(),
            Sha256d::from_slice(&[0, 0]).unwrap_err().to_string(),
        );
        Ok(())
    }

    #[test]
    fn test_sha256d_hex_be() -> Result<()> {
        const EMPTY_SHA256D: &str =
            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456";
        assert_eq!(Sha256d::digest(b"").to_hex_be(), EMPTY_SHA256D);
        assert_eq!(Sha256d::digest(b""), Sha256d::from_hex_be(EMPTY_SHA256D)?);
        Ok(())
    }

    #[test]
    fn test_sha256d_hex_le() -> Result<()> {
        const EMPTY_SHA256D_LE: &str =
            "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d";
        assert_eq!(Sha256d::digest(b"").to_hex_le(), EMPTY_SHA256D_LE);
        assert_eq!(
            Sha256d::digest(b""),
            Sha256d::from_hex_le(EMPTY_SHA256D_LE)?
        );
        Ok(())
    }

    #[test]
    fn test_hash160_slice() -> Result<()> {
        const EMPTY_HASH160: [u8; 20] = hex!("b472a266d0bd89c13706a4132ccfb16f7c3b9fcb");
        assert_eq!(Hash160::digest(b"").as_slice(), EMPTY_HASH160);
        assert_eq!(Hash160::digest(b""), Hash160::from_slice(&EMPTY_HASH160)?);
        assert_eq!(
            Error::ByteArrayError(ByteArrayError::InvalidSlice {
                expected: 20,
                actual: 2,
            })
            .to_string(),
            Hash160::from_slice(&[0, 0]).unwrap_err().to_string(),
        );
        Ok(())
    }

    #[test]
    fn test_hash160_hex_be() -> Result<()> {
        const EMPTY_HASH160: &str = "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb";
        assert_eq!(Hash160::digest(b"").to_hex_be(), EMPTY_HASH160);
        assert_eq!(Hash160::digest(b""), Hash160::from_hex_be(EMPTY_HASH160)?);
        Ok(())
    }

    #[test]
    fn test_hash160_hex_le() -> Result<()> {
        const EMPTY_HASH160_LE: &str = "cb9f3b7c6fb1cf2c13a40637c189bdd066a272b4";
        assert_eq!(Hash160::digest(b"").to_hex_le(), EMPTY_HASH160_LE);
        assert_eq!(
            Hash160::digest(b""),
            Hash160::from_hex_le(EMPTY_HASH160_LE)?
        );
        Ok(())
    }
}