Fix up TransparentAddresses

This commit is contained in:
Deirdre Connolly 2020-03-05 20:19:10 -05:00 committed by Deirdre Connolly
parent 16ee53a909
commit 9887b7c8b7
4 changed files with 97 additions and 42 deletions

7
Cargo.lock generated
View File

@ -191,6 +191,12 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "bs58"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae"
[[package]] [[package]]
name = "byte-tools" name = "byte-tools"
version = "0.3.1" version = "0.3.1"
@ -2036,6 +2042,7 @@ dependencies = [
name = "zebra-chain" name = "zebra-chain"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bs58",
"byteorder", "byteorder",
"chrono", "chrono",
"ed25519-zebra", "ed25519-zebra",

View File

@ -8,6 +8,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bs58 = "0.3.0"
byteorder = "1.3" byteorder = "1.3"
chrono = "0.4" chrono = "0.4"
futures = "0.3" futures = "0.3"

View File

@ -1,13 +1,16 @@
//! Address types. //! Address types.
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::{fmt, io};
use ripemd160::Ripdemd160;
use bs58;
use ripemd160::{Digest, Ripemd160};
use secp256k1::PublicKey; use secp256k1::PublicKey;
use sha2::Sha256; use sha2::Sha256;
use crate::serialization::{ #[cfg(test)]
ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashSerialize, use proptest_derive::Arbitrary;
};
use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize};
use crate::types::Script; use crate::types::Script;
@ -19,11 +22,15 @@ use crate::types::Script;
/// https://en.bitcoin.it/Base58Check_encoding#Encoding_a_Bitcoin_address /// https://en.bitcoin.it/Base58Check_encoding#Encoding_a_Bitcoin_address
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(test, derive(Arbitrary))] #[cfg_attr(test, derive(Arbitrary))]
struct AddressPayloadHash(pub [u8; 20]); pub struct AddressPayloadHash(pub [u8; 20]);
impl<'a> From<&'a [u8]> for AddressPayloadHash { impl<'a> From<&'a [u8]> for AddressPayloadHash {
fn from(bytes: &'a [u8]) -> Self { 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. /// An enum describing the possible network choices.
// XXX Stolen from zebra-network for now. // 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 { pub enum Network {
/// The production mainnet. /// The production mainnet.
Mainnet, Mainnet,
@ -57,42 +64,89 @@ pub enum Network {
/// ///
/// https://zips.z.cash/protocol/protocol.pdf#transparentaddrencoding /// https://zips.z.cash/protocol/protocol.pdf#transparentaddrencoding
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(test, derive(Arbitrary))] // #[cfg_attr(test, derive(Arbitrary))]
pub enum TransparentAddress { pub enum TransparentAddress {
/// P2SH (Pay to Script Hash) addresses
PayToScriptHash { PayToScriptHash {
/// Production, test, or other network
network: Network, network: Network,
script: AddressPayloadHash, /// 20 bytes specifying a script hash.
script_hash: AddressPayloadHash,
}, },
/// P2PKH (Pay to Public Key Hash) addresses
PayToPublicKeyHash { PayToPublicKeyHash {
/// Production, test, or other network
network: 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<Script> for TransparentAddress {
fn from(script: Script) -> Self {
TransparentAddress::PayToScriptHash {
network: Network::Mainnet,
script_hash: AddressPayloadHash::from(&script.0[..]),
}
}
}
impl From<PublicKey> for TransparentAddress {
fn from(pub_key: PublicKey) -> Self {
TransparentAddress::PayToPublicKeyHash {
network: Network::Mainnet,
pub_key_hash: AddressPayloadHash::from(&pub_key.serialize()[..]),
}
}
}
impl fmt::Debug for TransparentAddress {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut bytes = io::Cursor::new(Vec::new());
let _ = self.zcash_serialize(&mut bytes);
f.debug_tuple("TransparentAddress")
.field(&bs58::encode(bytes.get_ref()).into_vec())
.finish()
}
}
impl ZcashSerialize for TransparentAddress { impl ZcashSerialize for TransparentAddress {
fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> { fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
match self { match self {
TransparentAddress::PayToScriptHash { network, script_hash } => { TransparentAddress::PayToScriptHash {
if network == Network::Mainnet { network,
script_hash,
} => {
if *network == Network::Mainnet {
writer.write_all(&[0x1C, 0xBD][..])? writer.write_all(&[0x1C, 0xBD][..])?
} else { } else {
// Dev network doesn't have a recommendation so we // Dev network doesn't have a recommendation so we
// default to testnet bytes. // default to testnet bytes.
writer.write_all(&[0x1C, 0xBA][..])? writer.write_all(&[0x1C, 0xBA][..])?
} }
writer.write_all::<BigEndian>(script_hash[..])? // XXX I'm asuming this is BigEndian because we're not
// explicitly making it LittleEndian?
writer.write_all(&script_hash.0)?
} }
TransparentAddress::PayToPublicKeyHash{network, pub_key_hash) => { TransparentAddress::PayToPublicKeyHash {
if network == Network::Mainnet { network,
pub_key_hash,
} => {
if *network == Network::Mainnet {
writer.write_all(&[0x1C, 0xB8][..])? writer.write_all(&[0x1C, 0xB8][..])?
} else { } else {
// Dev network doesn't have a recommendation so we // Dev network doesn't have a recommendation so we
// default to testnet bytes. // default to testnet bytes.
writer.write_all(&[0x1D, 0x25][..])? writer.write_all(&[0x1D, 0x25][..])?
} }
writer.write_all::<BigEndian>(hash[..])? // XXX I'm asuming this is BigEndian because we're not
// explicitly making it LittleEndian?
writer.write_all(&pub_key_hash.0)?
} }
} }
Ok(())
} }
} }
@ -105,32 +159,25 @@ impl ZcashDeserialize for TransparentAddress {
reader.read_exact(&mut hash_bytes)?; reader.read_exact(&mut hash_bytes)?;
match version_bytes { match version_bytes {
[0x1c, 0xbd] => { [0x1c, 0xbd] => Ok(TransparentAddress::PayToScriptHash {
Ok(TransparentAddress::PayToScriptHash { network: Network::Mainnet,
network: Network::Mainnet, script_hash: AddressPayloadHash(hash_bytes),
script: AddressPayloadHash(hash_bytes) }),
})
},
// Currently only reading !mainnet versions as testnet. // Currently only reading !mainnet versions as testnet.
[0x1c, 0xba] => { [0x1c, 0xba] => Ok(TransparentAddress::PayToScriptHash {
Ok(TransparentAddress::PayToScriptHash { network: Network::Testnet,
network: Network::Testnet, script_hash: AddressPayloadHash(hash_bytes),
script: AddressPayloadHash(hash_bytes) }),
}) [0x1c, 0xb8] => Ok(TransparentAddress::PayToPublicKeyHash {
}, network: Network::Mainnet,
[0x1c, 0xb8] => { pub_key_hash: AddressPayloadHash(hash_bytes),
Ok(TransparentAddress::PayToPublicKeyHash { }),
network: Network::Mainnet,
pub_key: AddressPayloadHash(hash_bytes)
})
},
// Currently only reading !mainnet versions as testnet. // Currently only reading !mainnet versions as testnet.
[0x1d, 0x25] => { [0x1d, 0x25] => Ok(TransparentAddress::PayToPublicKeyHash {
Ok(TransparentAddress::PayToPublicKeyHash { network: Network::Testnet,
network: Network::Testnet, pub_key_hash: AddressPayloadHash(hash_bytes),
pub_key: AddressPayloadHash(hash_bytes) }),
}) _ => Err(SerializationError::Parse("bad t-addr version/type")),
}
} }
} }
} }

View File

@ -2,12 +2,12 @@
#![doc(html_logo_url = "https://www.zfnd.org/images/zebra-icon.png")] #![doc(html_logo_url = "https://www.zfnd.org/images/zebra-icon.png")]
#![doc(html_root_url = "https://doc.zebra.zfnd.org/zebra_chain")] #![doc(html_root_url = "https://doc.zebra.zfnd.org/zebra_chain")]
#![deny(missing_docs)] #![deny(missing_docs)]
mod merkle_tree; mod merkle_tree;
mod sha256d_writer; mod sha256d_writer;
pub mod addresses;
pub mod block; pub mod block;
pub mod equihash_solution; pub mod equihash_solution;
pub mod keys; pub mod keys;