diff --git a/Cargo.lock b/Cargo.lock index 36306cf7..9f28140b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,6 +191,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "bs58" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" + [[package]] name = "byte-tools" version = "0.3.1" @@ -2036,6 +2042,7 @@ dependencies = [ name = "zebra-chain" version = "0.1.0" dependencies = [ + "bs58", "byteorder", "chrono", "ed25519-zebra", diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 907aab35..f0a487ef 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bs58 = "0.3.0" byteorder = "1.3" chrono = "0.4" futures = "0.3" diff --git a/zebra-chain/src/addresses.rs b/zebra-chain/src/addresses.rs index 51ec86aa..040d0ca0 100644 --- a/zebra-chain/src/addresses.rs +++ b/zebra-chain/src/addresses.rs @@ -1,13 +1,16 @@ //! Address types. -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use ripemd160::Ripdemd160; +use std::{fmt, io}; + +use bs58; +use ripemd160::{Digest, Ripemd160}; use secp256k1::PublicKey; use sha2::Sha256; -use crate::serialization::{ - ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashSerialize, -}; +#[cfg(test)] +use proptest_derive::Arbitrary; + +use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; use crate::types::Script; @@ -19,11 +22,15 @@ use crate::types::Script; /// https://en.bitcoin.it/Base58Check_encoding#Encoding_a_Bitcoin_address #[derive(Copy, Clone, Eq, PartialEq)] #[cfg_attr(test, derive(Arbitrary))] -struct AddressPayloadHash(pub [u8; 20]); +pub struct AddressPayloadHash(pub [u8; 20]); impl<'a> From<&'a [u8]> for AddressPayloadHash { fn from(bytes: &'a [u8]) -> Self { - Self(Ripdemd160::digest(Sha256::digest(bytes))) + let sha_hash = Sha256::digest(bytes); + let ripe_hash = Ripemd160::digest(&sha_hash); + let mut payload = [0u8; 20]; + payload[..].copy_from_slice(&ripe_hash[..]); + Self(payload) } } @@ -37,7 +44,7 @@ impl fmt::Debug for AddressPayloadHash { /// An enum describing the possible network choices. // XXX Stolen from zebra-network for now. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum Network { /// The production mainnet. Mainnet, @@ -57,42 +64,89 @@ pub enum Network { /// /// https://zips.z.cash/protocol/protocol.pdf#transparentaddrencoding #[derive(Copy, Clone, Eq, PartialEq)] -#[cfg_attr(test, derive(Arbitrary))] +// #[cfg_attr(test, derive(Arbitrary))] pub enum TransparentAddress { + /// P2SH (Pay to Script Hash) addresses PayToScriptHash { + /// Production, test, or other network network: Network, - script: AddressPayloadHash, + /// 20 bytes specifying a script hash. + script_hash: AddressPayloadHash, }, + /// P2PKH (Pay to Public Key Hash) addresses PayToPublicKeyHash { + /// Production, test, or other network network: Network, - pub_key: AddressPayloadHash, + /// 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: AddressPayloadHash, }, } +impl From