Remove generating and validating transparent addresses
This commit is contained in:
parent
275e99ec72
commit
6f23d0e95b
|
|
@ -2,16 +2,13 @@
|
||||||
//!
|
//!
|
||||||
//! Usage: <https://docs.rs/zcash_address/0.2.0/zcash_address/trait.TryFromAddress.html#examples>
|
//! Usage: <https://docs.rs/zcash_address/0.2.0/zcash_address/trait.TryFromAddress.html#examples>
|
||||||
|
|
||||||
use zcash_address::unified::{self, Container};
|
use zcash_address::unified::{self, Container, Receiver};
|
||||||
use zcash_primitives::sapling;
|
use zcash_primitives::sapling;
|
||||||
|
|
||||||
use crate::{parameters::NetworkKind, transparent, BoxError};
|
use crate::{parameters::NetworkKind, transparent, BoxError};
|
||||||
|
|
||||||
/// Zcash address variants
|
/// Zcash address variants
|
||||||
pub enum Address {
|
pub enum Address {
|
||||||
/// Transparent address
|
|
||||||
Transparent(transparent::Address),
|
|
||||||
|
|
||||||
/// Sapling address
|
/// Sapling address
|
||||||
Sapling {
|
Sapling {
|
||||||
/// Address' network kind
|
/// Address' network kind
|
||||||
|
|
@ -34,9 +31,6 @@ pub enum Address {
|
||||||
|
|
||||||
/// Sapling address
|
/// Sapling address
|
||||||
sapling: Option<sapling::PaymentAddress>,
|
sapling: Option<sapling::PaymentAddress>,
|
||||||
|
|
||||||
/// Transparent address
|
|
||||||
transparent: Option<transparent::Address>,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,26 +38,6 @@ impl zcash_address::TryFromAddress for Address {
|
||||||
// TODO: crate::serialization::SerializationError
|
// TODO: crate::serialization::SerializationError
|
||||||
type Error = BoxError;
|
type Error = BoxError;
|
||||||
|
|
||||||
fn try_from_transparent_p2pkh(
|
|
||||||
network: zcash_address::Network,
|
|
||||||
data: [u8; 20],
|
|
||||||
) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
|
|
||||||
Ok(Self::Transparent(transparent::Address::from_pub_key_hash(
|
|
||||||
NetworkKind::from_zcash_address(network),
|
|
||||||
data,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_from_transparent_p2sh(
|
|
||||||
network: zcash_address::Network,
|
|
||||||
data: [u8; 20],
|
|
||||||
) -> Result<Self, zcash_address::ConversionError<Self::Error>> {
|
|
||||||
Ok(Self::Transparent(transparent::Address::from_script_hash(
|
|
||||||
NetworkKind::from_zcash_address(network),
|
|
||||||
data,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_from_sapling(
|
fn try_from_sapling(
|
||||||
network: zcash_address::Network,
|
network: zcash_address::Network,
|
||||||
data: [u8; 43],
|
data: [u8; 43],
|
||||||
|
|
@ -81,7 +55,6 @@ impl zcash_address::TryFromAddress for Address {
|
||||||
let network = NetworkKind::from_zcash_address(network);
|
let network = NetworkKind::from_zcash_address(network);
|
||||||
let mut orchard = None;
|
let mut orchard = None;
|
||||||
let mut sapling = None;
|
let mut sapling = None;
|
||||||
let mut transparent = None;
|
|
||||||
|
|
||||||
for receiver in unified_address.items().into_iter() {
|
for receiver in unified_address.items().into_iter() {
|
||||||
match receiver {
|
match receiver {
|
||||||
|
|
@ -109,15 +82,10 @@ impl zcash_address::TryFromAddress for Address {
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unified::Receiver::P2pkh(data) => {
|
|
||||||
transparent = Some(transparent::Address::from_pub_key_hash(network, data));
|
|
||||||
}
|
|
||||||
unified::Receiver::P2sh(data) => {
|
|
||||||
transparent = Some(transparent::Address::from_script_hash(network, data));
|
|
||||||
}
|
|
||||||
unified::Receiver::Unknown { .. } => {
|
unified::Receiver::Unknown { .. } => {
|
||||||
return Err(BoxError::from("Unsupported receiver in a Unified Address.").into());
|
return Err(BoxError::from("Unsupported receiver in a Unified Address.").into());
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,7 +94,6 @@ impl zcash_address::TryFromAddress for Address {
|
||||||
unified_address,
|
unified_address,
|
||||||
orchard,
|
orchard,
|
||||||
sapling,
|
sapling,
|
||||||
transparent,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +102,6 @@ impl Address {
|
||||||
/// Returns the network for the address.
|
/// Returns the network for the address.
|
||||||
pub fn network(&self) -> NetworkKind {
|
pub fn network(&self) -> NetworkKind {
|
||||||
match &self {
|
match &self {
|
||||||
Self::Transparent(address) => address.network_kind(),
|
|
||||||
Self::Sapling { network, .. } | Self::Unified { network, .. } => *network,
|
Self::Sapling { network, .. } | Self::Unified { network, .. } => *network,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -144,23 +110,16 @@ impl Address {
|
||||||
/// Returns false if the address is PayToPublicKeyHash or shielded.
|
/// Returns false if the address is PayToPublicKeyHash or shielded.
|
||||||
pub fn is_script_hash(&self) -> bool {
|
pub fn is_script_hash(&self) -> bool {
|
||||||
match &self {
|
match &self {
|
||||||
Self::Transparent(address) => address.is_script_hash(),
|
|
||||||
Self::Sapling { .. } | Self::Unified { .. } => false,
|
Self::Sapling { .. } | Self::Unified { .. } => false,
|
||||||
|
_ => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if address is of the [`Address::Transparent`] variant.
|
|
||||||
/// Returns false if otherwise.
|
|
||||||
pub fn is_transparent(&self) -> bool {
|
|
||||||
matches!(self, Self::Transparent(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the payment address for transparent or sapling addresses.
|
/// Returns the payment address for transparent or sapling addresses.
|
||||||
pub fn payment_address(&self) -> Option<String> {
|
pub fn payment_address(&self) -> Option<String> {
|
||||||
use zcash_address::{ToAddress, ZcashAddress};
|
use zcash_address::{ToAddress, ZcashAddress};
|
||||||
|
|
||||||
match &self {
|
match &self {
|
||||||
Self::Transparent(address) => Some(address.to_string()),
|
|
||||||
Self::Sapling { address, network } => {
|
Self::Sapling { address, network } => {
|
||||||
let data = address.to_bytes();
|
let data = address.to_bytes();
|
||||||
let address = ZcashAddress::from_sapling(network.to_zcash_address(), data);
|
let address = ZcashAddress::from_sapling(network.to_zcash_address(), data);
|
||||||
|
|
|
||||||
|
|
@ -1091,11 +1091,6 @@ where
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// we want to match zcashd's behaviour
|
|
||||||
if !address.is_transparent() {
|
|
||||||
return Ok(validate_address::Response::invalid());
|
|
||||||
}
|
|
||||||
|
|
||||||
if address.network() == network.kind() {
|
if address.network() == network.kind() {
|
||||||
Ok(validate_address::Response {
|
Ok(validate_address::Response {
|
||||||
address: Some(raw_address),
|
address: Some(raw_address),
|
||||||
|
|
@ -1308,8 +1303,6 @@ where
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut p2pkh = String::new();
|
|
||||||
let mut p2sh = String::new();
|
|
||||||
let mut orchard = String::new();
|
let mut orchard = String::new();
|
||||||
let mut sapling = String::new();
|
let mut sapling = String::new();
|
||||||
|
|
||||||
|
|
@ -1326,26 +1319,12 @@ where
|
||||||
.expect("using data already decoded as valid");
|
.expect("using data already decoded as valid");
|
||||||
sapling = addr.payment_address().unwrap_or_default();
|
sapling = addr.payment_address().unwrap_or_default();
|
||||||
}
|
}
|
||||||
zcash_address::unified::Receiver::P2pkh(data) => {
|
|
||||||
let addr = zebra_chain::primitives::Address::try_from_transparent_p2pkh(
|
|
||||||
network, data,
|
|
||||||
)
|
|
||||||
.expect("using data already decoded as valid");
|
|
||||||
p2pkh = addr.payment_address().unwrap_or_default();
|
|
||||||
}
|
|
||||||
zcash_address::unified::Receiver::P2sh(data) => {
|
|
||||||
let addr = zebra_chain::primitives::Address::try_from_transparent_p2sh(
|
|
||||||
network, data,
|
|
||||||
)
|
|
||||||
.expect("using data already decoded as valid");
|
|
||||||
p2sh = addr.payment_address().unwrap_or_default();
|
|
||||||
}
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(unified_address::Response::new(
|
Ok(unified_address::Response::new(
|
||||||
orchard, sapling, p2pkh, p2sh,
|
orchard, sapling,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
.boxed()
|
.boxed()
|
||||||
|
|
|
||||||
|
|
@ -7,20 +7,14 @@ pub struct Response {
|
||||||
orchard: String,
|
orchard: String,
|
||||||
#[serde(skip_serializing_if = "String::is_empty")]
|
#[serde(skip_serializing_if = "String::is_empty")]
|
||||||
sapling: String,
|
sapling: String,
|
||||||
#[serde(skip_serializing_if = "String::is_empty")]
|
|
||||||
p2pkh: String,
|
|
||||||
#[serde(skip_serializing_if = "String::is_empty")]
|
|
||||||
p2sh: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
/// Create a new response for z_listunifiedreceivers given individual addresses.
|
/// Create a new response for z_listunifiedreceivers given individual addresses.
|
||||||
pub fn new(orchard: String, sapling: String, p2pkh: String, p2sh: String) -> Response {
|
pub fn new(orchard: String, sapling: String) -> Response {
|
||||||
Response {
|
Response {
|
||||||
orchard,
|
orchard,
|
||||||
sapling,
|
sapling,
|
||||||
p2pkh,
|
|
||||||
p2sh,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,22 +35,4 @@ impl Response {
|
||||||
false => Some(self.sapling.clone()),
|
false => Some(self.sapling.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
/// Return the p2pkh payment address from a response, if any.
|
|
||||||
pub fn p2pkh(&self) -> Option<String> {
|
|
||||||
match self.p2pkh.is_empty() {
|
|
||||||
true => None,
|
|
||||||
false => Some(self.p2pkh.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
/// Return the p2sh payment address from a response, if any.
|
|
||||||
pub fn p2sh(&self) -> Option<String> {
|
|
||||||
match self.p2sh.is_empty() {
|
|
||||||
true => None,
|
|
||||||
false => Some(self.p2sh.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,6 @@ impl Response {
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum AddressType {
|
pub enum AddressType {
|
||||||
/// The `p2pkh` address type.
|
|
||||||
P2pkh,
|
|
||||||
/// The `p2sh` address type.
|
|
||||||
P2sh,
|
|
||||||
/// The `sapling` address type.
|
/// The `sapling` address type.
|
||||||
Sapling,
|
Sapling,
|
||||||
/// The `unified` address type.
|
/// The `unified` address type.
|
||||||
|
|
@ -52,13 +48,6 @@ pub enum AddressType {
|
||||||
impl From<&Address> for AddressType {
|
impl From<&Address> for AddressType {
|
||||||
fn from(address: &Address) -> Self {
|
fn from(address: &Address) -> Self {
|
||||||
match address {
|
match address {
|
||||||
Address::Transparent(_) => {
|
|
||||||
if address.is_script_hash() {
|
|
||||||
Self::P2sh
|
|
||||||
} else {
|
|
||||||
Self::P2pkh
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Address::Sapling { .. } => Self::Sapling,
|
Address::Sapling { .. } => Self::Sapling,
|
||||||
Address::Unified { .. } => Self::Unified,
|
Address::Unified { .. } => Self::Unified,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1903,19 +1903,9 @@ async fn rpc_z_listunifiedreceivers() {
|
||||||
"zs1mrhc9y7jdh5r9ece8u5khgvj9kg0zgkxzdduyv0whkg7lkcrkx5xqem3e48avjq9wn2rukydkwn"
|
"zs1mrhc9y7jdh5r9ece8u5khgvj9kg0zgkxzdduyv0whkg7lkcrkx5xqem3e48avjq9wn2rukydkwn"
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
|
||||||
response.p2pkh(),
|
|
||||||
Some(String::from("t1V9mnyk5Z5cTNMCkLbaDwSskgJZucTLdgW"))
|
|
||||||
);
|
|
||||||
assert_eq!(response.p2sh(), None);
|
|
||||||
|
|
||||||
// address taken from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/test-vectors/zcash/unified_address.json#L39
|
// address taken from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/test-vectors/zcash/unified_address.json#L39
|
||||||
let response = get_block_template_rpc.z_list_unified_receivers("u12acx92vw49jek4lwwnjtzm0cssn2wxfneu7ryj4amd8kvnhahdrq0htsnrwhqvl92yg92yut5jvgygk0rqfs4lgthtycsewc4t57jyjn9p2g6ffxek9rdg48xe5kr37hxxh86zxh2ef0u2lu22n25xaf3a45as6mtxxlqe37r75mndzu9z2fe4h77m35c5mrzf4uqru3fjs39ednvw9ay8nf9r8g9jx8rgj50mj098exdyq803hmqsek3dwlnz4g5whc88mkvvjnfmjldjs9hm8rx89ctn5wxcc2e05rcz7m955zc7trfm07gr7ankf96jxwwfcqppmdefj8gc6508gep8ndrml34rdpk9tpvwzgdcv7lk2d70uh5jqacrpk6zsety33qcc554r3cls4ajktg03d9fye6exk8gnve562yadzsfmfh9d7v6ctl5ufm9ewpr6se25c47huk4fh2hakkwerkdd2yy3093snsgree5lt6smejfvse8v".to_string()).await.unwrap();
|
let response = get_block_template_rpc.z_list_unified_receivers("u12acx92vw49jek4lwwnjtzm0cssn2wxfneu7ryj4amd8kvnhahdrq0htsnrwhqvl92yg92yut5jvgygk0rqfs4lgthtycsewc4t57jyjn9p2g6ffxek9rdg48xe5kr37hxxh86zxh2ef0u2lu22n25xaf3a45as6mtxxlqe37r75mndzu9z2fe4h77m35c5mrzf4uqru3fjs39ednvw9ay8nf9r8g9jx8rgj50mj098exdyq803hmqsek3dwlnz4g5whc88mkvvjnfmjldjs9hm8rx89ctn5wxcc2e05rcz7m955zc7trfm07gr7ankf96jxwwfcqppmdefj8gc6508gep8ndrml34rdpk9tpvwzgdcv7lk2d70uh5jqacrpk6zsety33qcc554r3cls4ajktg03d9fye6exk8gnve562yadzsfmfh9d7v6ctl5ufm9ewpr6se25c47huk4fh2hakkwerkdd2yy3093snsgree5lt6smejfvse8v".to_string()).await.unwrap();
|
||||||
assert_eq!(response.orchard(), Some(String::from("u10c5q7qkhu6f0ktaz7jqu4sfsujg0gpsglzudmy982mku7t0uma52jmsaz8h24a3wa7p0jwtsjqt8shpg25cvyexzlsw3jtdz4v6w70lv")));
|
assert_eq!(response.orchard(), Some(String::from("u10c5q7qkhu6f0ktaz7jqu4sfsujg0gpsglzudmy982mku7t0uma52jmsaz8h24a3wa7p0jwtsjqt8shpg25cvyexzlsw3jtdz4v6w70lv")));
|
||||||
assert_eq!(response.sapling(), None);
|
assert_eq!(response.sapling(), None);
|
||||||
assert_eq!(
|
|
||||||
response.p2pkh(),
|
|
||||||
Some(String::from("t1dMjwmwM2a6NtavQ6SiPP8i9ofx4cgfYYP"))
|
|
||||||
);
|
|
||||||
assert_eq!(response.p2sh(), None);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue