zebra/zebra-chain/src/orchard/action.rs

105 lines
5.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::io;
use halo2::pasta::pallas;
use reddsa::orchard::SpendAuth;
use crate::serialization::{
serde_helpers, ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize,
};
use super::{
commitment::{self, ValueCommitment},
keys,
note::{self, Nullifier},
};
/// An Action description, as described in the [Zcash specification §7.3][actiondesc].
///
/// Action transfers can optionally perform a spend, and optionally perform an
/// output. Action descriptions are data included in a transaction that
/// describe Action transfers.
///
/// [actiondesc]: https://zips.z.cash/protocol/nu5.pdf#actiondesc
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Action {
/// A value commitment to net value of the input note minus the output note
pub cv: commitment::ValueCommitment,
/// The nullifier of the input note being spent.
pub nullifier: note::Nullifier,
/// The randomized validating key for spendAuthSig,
pub rk: reddsa::VerificationKeyBytes<SpendAuth>,
/// The x-coordinate of the note commitment for the output note.
#[serde(with = "serde_helpers::Base")]
pub cm_x: pallas::Base,
/// An encoding of an ephemeral Pallas public key corresponding to the
/// encrypted private key in `out_ciphertext`.
pub ephemeral_key: keys::EphemeralPublicKey,
/// A ciphertext component for the encrypted output note.
pub enc_ciphertext: note::EncryptedNote,
/// A ciphertext component that allows the holder of a full viewing key to
/// recover the recipient diversified transmission key and the ephemeral
/// private key (and therefore the entire note plaintext).
pub out_ciphertext: note::WrappedNoteKey,
}
impl ZcashSerialize for Action {
fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
self.cv.zcash_serialize(&mut writer)?;
writer.write_all(&<[u8; 32]>::from(self.nullifier)[..])?;
writer.write_all(&<[u8; 32]>::from(self.rk)[..])?;
writer.write_all(&<[u8; 32]>::from(self.cm_x)[..])?;
self.ephemeral_key.zcash_serialize(&mut writer)?;
self.enc_ciphertext.zcash_serialize(&mut writer)?;
self.out_ciphertext.zcash_serialize(&mut writer)?;
Ok(())
}
}
impl ZcashDeserialize for Action {
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
// # Consensus
//
// > Elements of an Action description MUST be canonical encodings of the types given above.
//
// https://zips.z.cash/protocol/protocol.pdf#actiondesc
//
// > LEOS2IP_{256}(cmx) MUST be less than 𝑞_.
//
// https://zips.z.cash/protocol/protocol.pdf#actionencodingandconsensus
//
// See comments below for each specific type.
Ok(Action {
// Type is ValueCommit^{Orchard}.Output, i.e. .
// https://zips.z.cash/protocol/protocol.pdf#abstractcommit
// See [`ValueCommitment::zcash_deserialize`].
cv: ValueCommitment::zcash_deserialize(&mut reader)?,
// Type is `{0 .. 𝑞_ 1}`. See [`Nullifier::try_from`].
nullifier: Nullifier::try_from(reader.read_32_bytes()?)?,
// Type is SpendAuthSig^{Orchard}.Public, i.e. .
// https://zips.z.cash/protocol/protocol.pdf#concretespendauthsig
// https://zips.z.cash/protocol/protocol.pdf#concretereddsa
// This only reads the 32-byte buffer. The type is enforced
// on signature verification; see [`reddsa::batch`]
rk: reader.read_32_bytes()?.into(),
// Type is `{0 .. 𝑞_ 1}`. Note that the second rule quoted above
// is also enforced here and it is technically redundant with the first.
// See [`pallas::Base::zcash_deserialize`].
cm_x: pallas::Base::zcash_deserialize(&mut reader)?,
// Denoted by `epk` in the spec. Type is KA^{Orchard}.Public, i.e. ^*.
// https://zips.z.cash/protocol/protocol.pdf#concreteorchardkeyagreement
// See [`keys::EphemeralPublicKey::zcash_deserialize`].
ephemeral_key: keys::EphemeralPublicKey::zcash_deserialize(&mut reader)?,
// Type is `Sym.C`, i.e. `𝔹^Y^{\[N\]}`, i.e. arbitrary-sized byte arrays
// https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to
// 580 bytes in https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus
// See [`note::EncryptedNote::zcash_deserialize`].
enc_ciphertext: note::EncryptedNote::zcash_deserialize(&mut reader)?,
// Type is `Sym.C`, i.e. `𝔹^Y^{\[N\]}`, i.e. arbitrary-sized byte arrays
// https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to
// 80 bytes in https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus
// See [`note::WrappedNoteKey::zcash_deserialize`].
out_ciphertext: note::WrappedNoteKey::zcash_deserialize(&mut reader)?,
})
}
}