//! Transparent Address types. use std::{fmt, io}; use bs58; use ripemd160::{Digest, Ripemd160}; use secp256k1::PublicKey; use sha2::Sha256; #[cfg(test)] use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*}; use crate::{ serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}, types::Script, Network, }; /// Magic numbers used to identify what networks Transparent Addresses /// are associated with. mod magics { pub mod p2sh { pub const MAINNET: [u8; 2] = [0x1C, 0xBD]; pub const TESTNET: [u8; 2] = [0x1C, 0xBA]; } pub mod p2pkh { pub const MAINNET: [u8; 2] = [0x1C, 0xB8]; pub const TESTNET: [u8; 2] = [0x1D, 0x25]; } } /// Transparent Zcash Addresses /// /// In Bitcoin a single byte is used for the version field identifying /// the address type. In Zcash two bytes are used. For addresses on /// the production network, this and the encoded length cause the first /// two characters of the Base58Check encoding to be fixed as “t3” for /// P2SH addresses, and as “t1” for P2PKH addresses. (This does not /// imply that a transparent Zcash address can be parsed identically /// to a Bitcoin address just by removing the “t”.) /// /// https://zips.z.cash/protocol/protocol.pdf#transparentaddrencoding #[derive(Copy, Clone, Eq, PartialEq)] pub enum TransparentAddress { /// P2SH (Pay to Script Hash) addresses PayToScriptHash { /// Production, test, or other network network: Network, /// 20 bytes specifying a script hash. script_hash: [u8; 20], }, /// P2PKH (Pay to Public Key Hash) addresses PayToPublicKeyHash { /// Production, test, or other network network: Network, /// 20 bytes specifying a public key hash, which is a RIPEMD-160 /// hash of a SHA-256 hash of a compressed ECDSA key encoding. pub_key_hash: [u8; 20], }, } impl TransparentAddress { /// A hash of a transparent address payload, as used in /// transparent pay-to-script-hash and pay-to-publickey-hash /// addresses. /// /// The resulting hash in both of these cases is always exactly 20 /// bytes. /// https://en.bitcoin.it/Base58Check_encoding#Encoding_a_Bitcoin_address fn hash_payload(bytes: &[u8]) -> [u8; 20] { let sha_hash = Sha256::digest(bytes); let ripe_hash = Ripemd160::digest(&sha_hash); let mut payload = [0u8; 20]; payload[..].copy_from_slice(&ripe_hash[..]); payload } } impl From