use std::io; use crate::{ primitives::{ redjubjub::{self, SpendAuth}, Groth16Proof, }, serialization::{ ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashSerialize, }, }; use super::{commitment, note, tree}; /// A _Spend Description_, as described in [protocol specification ยง7.3][ps]. /// /// [ps]: https://zips.z.cash/protocol/protocol.pdf#spendencoding #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Spend { /// A value commitment to the value of the input note. pub cv: commitment::ValueCommitment, /// A root of the Sapling note commitment tree at some block height in the past. pub anchor: tree::Root, /// The nullifier of the input note. pub nullifier: note::Nullifier, /// The randomized public key for `spend_auth_sig`. pub rk: redjubjub::VerificationKeyBytes, /// The ZK spend proof. pub zkproof: Groth16Proof, /// A signature authorizing this spend. pub spend_auth_sig: redjubjub::Signature, } impl ZcashSerialize for Spend { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { self.cv.zcash_serialize(&mut writer)?; writer.write_all(&self.anchor.0[..])?; writer.write_32_bytes(&self.nullifier.into())?; writer.write_all(&<[u8; 32]>::from(self.rk)[..])?; self.zkproof.zcash_serialize(&mut writer)?; writer.write_all(&<[u8; 64]>::from(self.spend_auth_sig)[..])?; Ok(()) } } impl ZcashDeserialize for Spend { fn zcash_deserialize(mut reader: R) -> Result { use crate::sapling::{commitment::ValueCommitment, note::Nullifier}; Ok(Spend { cv: ValueCommitment::zcash_deserialize(&mut reader)?, anchor: tree::Root(reader.read_32_bytes()?), nullifier: Nullifier::from(reader.read_32_bytes()?), rk: reader.read_32_bytes()?.into(), zkproof: Groth16Proof::zcash_deserialize(&mut reader)?, spend_auth_sig: reader.read_64_bytes()?.into(), }) } }