use zcash_primitives::{
block::{BlockHash, BlockHeader},
consensus::BlockHeight,
sapling::{note::ExtractedNoteCommitment, Nullifier},
transaction::{components::sapling, TxId},
};
use zcash_note_encryption::{EphemeralKeyBytes, COMPACT_NOTE_SIZE};
#[rustfmt::skip]
#[allow(unknown_lints)]
#[allow(clippy::derive_partial_eq_without_eq)]
pub mod compact_formats;
#[cfg(feature = "lightwalletd-tonic")]
#[rustfmt::skip]
#[allow(unknown_lints)]
#[allow(clippy::derive_partial_eq_without_eq)]
pub mod service;
impl compact_formats::CompactBlock {
pub fn hash(&self) -> BlockHash {
if let Some(header) = self.header() {
header.hash()
} else {
BlockHash::from_slice(&self.hash)
}
}
pub fn prev_hash(&self) -> BlockHash {
if let Some(header) = self.header() {
header.prev_block
} else {
BlockHash::from_slice(&self.prev_hash)
}
}
pub fn height(&self) -> BlockHeight {
self.height.try_into().unwrap()
}
pub fn header(&self) -> Option<BlockHeader> {
if self.header.is_empty() {
None
} else {
BlockHeader::read(&self.header[..]).ok()
}
}
}
impl compact_formats::CompactTx {
pub fn txid(&self) -> TxId {
let mut hash = [0u8; 32];
hash.copy_from_slice(&self.hash);
TxId::from_bytes(hash)
}
}
impl compact_formats::CompactSaplingOutput {
pub fn cmu(&self) -> Result<ExtractedNoteCommitment, ()> {
let mut repr = [0; 32];
repr.as_mut().copy_from_slice(&self.cmu[..]);
Option::from(ExtractedNoteCommitment::from_bytes(&repr)).ok_or(())
}
pub fn ephemeral_key(&self) -> Result<EphemeralKeyBytes, ()> {
self.ephemeral_key[..]
.try_into()
.map(EphemeralKeyBytes)
.map_err(|_| ())
}
}
impl<A: sapling::Authorization> From<sapling::OutputDescription<A>>
for compact_formats::CompactSaplingOutput
{
fn from(out: sapling::OutputDescription<A>) -> compact_formats::CompactSaplingOutput {
compact_formats::CompactSaplingOutput {
cmu: out.cmu().to_bytes().to_vec(),
ephemeral_key: out.ephemeral_key().as_ref().to_vec(),
ciphertext: out.enc_ciphertext()[..COMPACT_NOTE_SIZE].to_vec(),
}
}
}
impl TryFrom<compact_formats::CompactSaplingOutput> for sapling::CompactOutputDescription {
type Error = ();
fn try_from(value: compact_formats::CompactSaplingOutput) -> Result<Self, Self::Error> {
Ok(sapling::CompactOutputDescription {
cmu: value.cmu()?,
ephemeral_key: value.ephemeral_key()?,
enc_ciphertext: value.ciphertext.try_into().map_err(|_| ())?,
})
}
}
impl compact_formats::CompactSaplingSpend {
pub fn nf(&self) -> Result<Nullifier, ()> {
Nullifier::from_slice(&self.nf).map_err(|_| ())
}
}