#![cfg_attr(feature = "std", doc = "## Feature flags")]
#![cfg_attr(feature = "std", doc = document_features::document_features!())]
#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, doc(auto_cfg))]
#![deny(rustdoc::broken_intra_doc_links)]
#[macro_use]
extern crate alloc;
use alloc::vec::Vec;
use getset::Getters;
use serde::{Deserialize, Serialize};
#[cfg(feature = "signer")]
use {roles::signer::EffectsOnly, zcash_primitives::transaction::TransactionData};
pub mod roles;
pub mod common;
pub mod orchard;
pub mod sapling;
pub mod transparent;
const MAGIC_BYTES: &[u8] = b"PCZT";
const PCZT_VERSION_1: u32 = 1;
#[derive(Clone, Debug, Serialize, Deserialize, Getters)]
pub struct Pczt {
#[getset(get = "pub")]
global: common::Global,
#[getset(get = "pub")]
transparent: transparent::Bundle,
#[getset(get = "pub")]
sapling: sapling::Bundle,
#[getset(get = "pub")]
orchard: orchard::Bundle,
}
impl Pczt {
pub fn parse(bytes: &[u8]) -> Result<Self, ParseError> {
if bytes.len() < 8 {
return Err(ParseError::TooShort);
}
if &bytes[..4] != MAGIC_BYTES {
return Err(ParseError::NotPczt);
}
let version = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
if version != PCZT_VERSION_1 {
return Err(ParseError::UnknownVersion(version));
}
postcard::from_bytes(&bytes[8..]).map_err(ParseError::Invalid)
}
pub fn serialize(&self) -> Vec<u8> {
let mut bytes = vec![];
bytes.extend_from_slice(MAGIC_BYTES);
bytes.extend_from_slice(&PCZT_VERSION_1.to_le_bytes());
postcard::to_extend(self, bytes).expect("can serialize into memory")
}
#[cfg(feature = "signer")]
pub fn into_effects(self) -> Option<TransactionData<EffectsOnly>> {
let Self {
global,
transparent,
sapling,
orchard,
} = self;
let transparent = transparent.into_parsed().ok()?;
let sapling = sapling.into_parsed().ok()?;
let orchard = orchard.into_parsed().ok()?;
roles::signer::pczt_to_tx_data(&global, &transparent, &sapling, &orchard).ok()
}
}
#[derive(Debug)]
pub enum ParseError {
NotPczt,
Invalid(postcard::Error),
TooShort,
UnknownVersion(u32),
}