Implement TransparentAddress encoding and decoding
This commit is contained in:
parent
97c21e0c1a
commit
932f1c9737
|
@ -13,6 +13,7 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bech32 = "0.7"
|
bech32 = "0.7"
|
||||||
|
bs58 = { version = "0.3", features = ["check"] }
|
||||||
ff = { version = "0.6", path = "../ff" }
|
ff = { version = "0.6", path = "../ff" }
|
||||||
hex = "0.3"
|
hex = "0.3"
|
||||||
pairing = { version = "0.16", path = "../pairing" }
|
pairing = { version = "0.16", path = "../pairing" }
|
||||||
|
|
|
@ -28,3 +28,13 @@ pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviews";
|
||||||
/// [`PaymentAddress`]: zcash_primitives::primitives::PaymentAddress
|
/// [`PaymentAddress`]: zcash_primitives::primitives::PaymentAddress
|
||||||
/// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
|
/// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
|
||||||
pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "zs";
|
pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "zs";
|
||||||
|
|
||||||
|
/// The prefix for a Base58Check-encoded mainnet [`TransparentAddress::PublicKey`].
|
||||||
|
///
|
||||||
|
/// [`TransparentAddress::PublicKey`]: zcash_primitives::legacy::TransparentAddress::PublicKey
|
||||||
|
pub const B58_PUBKEY_ADDRESS_PREFIX: [u8; 2] = [0x1c, 0xb8];
|
||||||
|
|
||||||
|
/// The prefix for a Base58Check-encoded mainnet [`TransparentAddress::Script`].
|
||||||
|
///
|
||||||
|
/// [`TransparentAddress::Script`]: zcash_primitives::legacy::TransparentAddress::Script
|
||||||
|
pub const B58_SCRIPT_ADDRESS_PREFIX: [u8; 2] = [0x1c, 0xbd];
|
||||||
|
|
|
@ -28,3 +28,13 @@ pub const HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY: &str = "zxviewtestsapling";
|
||||||
/// [`PaymentAddress`]: zcash_primitives::primitives::PaymentAddress
|
/// [`PaymentAddress`]: zcash_primitives::primitives::PaymentAddress
|
||||||
/// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
|
/// [Zcash Protocol Specification]: https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
|
||||||
pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "ztestsapling";
|
pub const HRP_SAPLING_PAYMENT_ADDRESS: &str = "ztestsapling";
|
||||||
|
|
||||||
|
/// The prefix for a Base58Check-encoded testnet [`TransparentAddress::PublicKey`].
|
||||||
|
///
|
||||||
|
/// [`TransparentAddress::PublicKey`]: zcash_primitives::legacy::TransparentAddress::PublicKey
|
||||||
|
pub const B58_PUBKEY_ADDRESS_PREFIX: [u8; 2] = [0x1d, 0x25];
|
||||||
|
|
||||||
|
/// The prefix for a Base58Check-encoded testnet [`TransparentAddress::Script`].
|
||||||
|
///
|
||||||
|
/// [`TransparentAddress::Script`]: zcash_primitives::legacy::TransparentAddress::Script
|
||||||
|
pub const B58_SCRIPT_ADDRESS_PREFIX: [u8; 2] = [0x1c, 0xba];
|
||||||
|
|
|
@ -6,9 +6,12 @@
|
||||||
//! [`constants`]: crate::constants
|
//! [`constants`]: crate::constants
|
||||||
|
|
||||||
use bech32::{self, Error, FromBase32, ToBase32};
|
use bech32::{self, Error, FromBase32, ToBase32};
|
||||||
|
use bs58::{self, decode::Error as Bs58Error};
|
||||||
use pairing::bls12_381::Bls12;
|
use pairing::bls12_381::Bls12;
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
|
legacy::TransparentAddress,
|
||||||
primitives::PaymentAddress,
|
primitives::PaymentAddress,
|
||||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||||
JUBJUB,
|
JUBJUB,
|
||||||
|
@ -176,6 +179,108 @@ pub fn decode_payment_address(hrp: &str, s: &str) -> Result<Option<PaymentAddres
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Writes a [`TransparentAddress`] as a Base58Check-encoded string.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use zcash_client_backend::{
|
||||||
|
/// constants::testnet::{B58_PUBKEY_ADDRESS_PREFIX, B58_SCRIPT_ADDRESS_PREFIX},
|
||||||
|
/// encoding::encode_transparent_address,
|
||||||
|
/// };
|
||||||
|
/// use zcash_primitives::legacy::TransparentAddress;
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// encode_transparent_address(
|
||||||
|
/// &B58_PUBKEY_ADDRESS_PREFIX,
|
||||||
|
/// &B58_SCRIPT_ADDRESS_PREFIX,
|
||||||
|
/// &TransparentAddress::PublicKey([0; 20]),
|
||||||
|
/// ),
|
||||||
|
/// "tm9iMLAuYMzJ6jtFLcA7rzUmfreGuKvr7Ma",
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// encode_transparent_address(
|
||||||
|
/// &B58_PUBKEY_ADDRESS_PREFIX,
|
||||||
|
/// &B58_SCRIPT_ADDRESS_PREFIX,
|
||||||
|
/// &TransparentAddress::Script([0; 20]),
|
||||||
|
/// ),
|
||||||
|
/// "t26YoyZ1iPgiMEWL4zGUm74eVWfhyDMXzY2",
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn encode_transparent_address(
|
||||||
|
pubkey_version: &[u8],
|
||||||
|
script_version: &[u8],
|
||||||
|
addr: &TransparentAddress,
|
||||||
|
) -> String {
|
||||||
|
let decoded = match addr {
|
||||||
|
TransparentAddress::PublicKey(key_id) => {
|
||||||
|
let mut decoded = vec![0; pubkey_version.len() + 20];
|
||||||
|
decoded[..pubkey_version.len()].copy_from_slice(pubkey_version);
|
||||||
|
decoded[pubkey_version.len()..].copy_from_slice(key_id);
|
||||||
|
decoded
|
||||||
|
}
|
||||||
|
TransparentAddress::Script(script_id) => {
|
||||||
|
let mut decoded = vec![0; script_version.len() + 20];
|
||||||
|
decoded[..script_version.len()].copy_from_slice(script_version);
|
||||||
|
decoded[script_version.len()..].copy_from_slice(script_id);
|
||||||
|
decoded
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bs58::encode(decoded).with_check().into_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decodes a [`TransparentAddress`] from a Base58Check-encoded string.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use zcash_client_backend::{
|
||||||
|
/// constants::testnet::{B58_PUBKEY_ADDRESS_PREFIX, B58_SCRIPT_ADDRESS_PREFIX},
|
||||||
|
/// encoding::decode_transparent_address,
|
||||||
|
/// };
|
||||||
|
/// use zcash_primitives::legacy::TransparentAddress;
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// decode_transparent_address(
|
||||||
|
/// &B58_PUBKEY_ADDRESS_PREFIX,
|
||||||
|
/// &B58_SCRIPT_ADDRESS_PREFIX,
|
||||||
|
/// "tm9iMLAuYMzJ6jtFLcA7rzUmfreGuKvr7Ma",
|
||||||
|
/// ),
|
||||||
|
/// Ok(Some(TransparentAddress::PublicKey([0; 20]))),
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// decode_transparent_address(
|
||||||
|
/// &B58_PUBKEY_ADDRESS_PREFIX,
|
||||||
|
/// &B58_SCRIPT_ADDRESS_PREFIX,
|
||||||
|
/// "t26YoyZ1iPgiMEWL4zGUm74eVWfhyDMXzY2",
|
||||||
|
/// ),
|
||||||
|
/// Ok(Some(TransparentAddress::Script([0; 20]))),
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn decode_transparent_address(
|
||||||
|
pubkey_version: &[u8],
|
||||||
|
script_version: &[u8],
|
||||||
|
s: &str,
|
||||||
|
) -> Result<Option<TransparentAddress>, Bs58Error> {
|
||||||
|
bs58::decode(s).with_check(None).into_vec().map(|decoded| {
|
||||||
|
if decoded.starts_with(pubkey_version) {
|
||||||
|
decoded[pubkey_version.len()..]
|
||||||
|
.try_into()
|
||||||
|
.ok()
|
||||||
|
.map(TransparentAddress::PublicKey)
|
||||||
|
} else if decoded.starts_with(script_version) {
|
||||||
|
decoded[script_version.len()..]
|
||||||
|
.try_into()
|
||||||
|
.ok()
|
||||||
|
.map(TransparentAddress::Script)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pairing::bls12_381::Bls12;
|
use pairing::bls12_381::Bls12;
|
||||||
|
|
Loading…
Reference in New Issue