zebra_chain/orchard/action.rs
1use std::io;
2
3use halo2::pasta::pallas;
4use reddsa::orchard::SpendAuth;
5
6use crate::serialization::{
7 serde_helpers, ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize,
8};
9
10use super::{
11 commitment::{self, ValueCommitment},
12 keys,
13 note::{self, Nullifier},
14};
15
16/// An Action description, as described in the [Zcash specification §7.3][actiondesc].
17///
18/// Action transfers can optionally perform a spend, and optionally perform an
19/// output. Action descriptions are data included in a transaction that
20/// describe Action transfers.
21///
22/// [actiondesc]: https://zips.z.cash/protocol/nu5.pdf#actiondesc
23#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
24pub struct Action {
25 /// A value commitment to net value of the input note minus the output note
26 pub cv: commitment::ValueCommitment,
27 /// The nullifier of the input note being spent.
28 pub nullifier: note::Nullifier,
29 /// The randomized validating key for spendAuthSig,
30 pub rk: reddsa::VerificationKeyBytes<SpendAuth>,
31 /// The x-coordinate of the note commitment for the output note.
32 #[serde(with = "serde_helpers::Base")]
33 pub cm_x: pallas::Base,
34 /// An encoding of an ephemeral Pallas public key corresponding to the
35 /// encrypted private key in `out_ciphertext`.
36 pub ephemeral_key: keys::EphemeralPublicKey,
37 /// A ciphertext component for the encrypted output note.
38 pub enc_ciphertext: note::EncryptedNote,
39 /// A ciphertext component that allows the holder of a full viewing key to
40 /// recover the recipient diversified transmission key and the ephemeral
41 /// private key (and therefore the entire note plaintext).
42 pub out_ciphertext: note::WrappedNoteKey,
43}
44
45impl ZcashSerialize for Action {
46 fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
47 self.cv.zcash_serialize(&mut writer)?;
48 writer.write_all(&<[u8; 32]>::from(self.nullifier)[..])?;
49 writer.write_all(&<[u8; 32]>::from(self.rk)[..])?;
50 writer.write_all(&<[u8; 32]>::from(self.cm_x)[..])?;
51 self.ephemeral_key.zcash_serialize(&mut writer)?;
52 self.enc_ciphertext.zcash_serialize(&mut writer)?;
53 self.out_ciphertext.zcash_serialize(&mut writer)?;
54 Ok(())
55 }
56}
57
58impl ZcashDeserialize for Action {
59 fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
60 // # Consensus
61 //
62 // > Elements of an Action description MUST be canonical encodings of the types given above.
63 //
64 // https://zips.z.cash/protocol/protocol.pdf#actiondesc
65 //
66 // > LEOS2IP_{256}(cmx) MUST be less than 𝑞_ℙ.
67 //
68 // https://zips.z.cash/protocol/protocol.pdf#actionencodingandconsensus
69 //
70 // See comments below for each specific type.
71 Ok(Action {
72 // Type is ValueCommit^{Orchard}.Output, i.e. ℙ.
73 // https://zips.z.cash/protocol/protocol.pdf#abstractcommit
74 // See [`ValueCommitment::zcash_deserialize`].
75 cv: ValueCommitment::zcash_deserialize(&mut reader)?,
76 // Type is `{0 .. 𝑞_ℙ − 1}`. See [`Nullifier::try_from`].
77 nullifier: Nullifier::try_from(reader.read_32_bytes()?)?,
78 // Type is SpendAuthSig^{Orchard}.Public, i.e. ℙ.
79 // https://zips.z.cash/protocol/protocol.pdf#concretespendauthsig
80 // https://zips.z.cash/protocol/protocol.pdf#concretereddsa
81 // This only reads the 32-byte buffer. The type is enforced
82 // on signature verification; see [`reddsa::batch`]
83 rk: reader.read_32_bytes()?.into(),
84 // Type is `{0 .. 𝑞_ℙ − 1}`. Note that the second rule quoted above
85 // is also enforced here and it is technically redundant with the first.
86 // See [`pallas::Base::zcash_deserialize`].
87 cm_x: pallas::Base::zcash_deserialize(&mut reader)?,
88 // Denoted by `epk` in the spec. Type is KA^{Orchard}.Public, i.e. ℙ^*.
89 // https://zips.z.cash/protocol/protocol.pdf#concreteorchardkeyagreement
90 // See [`keys::EphemeralPublicKey::zcash_deserialize`].
91 ephemeral_key: keys::EphemeralPublicKey::zcash_deserialize(&mut reader)?,
92 // Type is `Sym.C`, i.e. `𝔹^Y^{\[N\]}`, i.e. arbitrary-sized byte arrays
93 // https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to
94 // 580 bytes in https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus
95 // See [`note::EncryptedNote::zcash_deserialize`].
96 enc_ciphertext: note::EncryptedNote::zcash_deserialize(&mut reader)?,
97 // Type is `Sym.C`, i.e. `𝔹^Y^{\[N\]}`, i.e. arbitrary-sized byte arrays
98 // https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to
99 // 80 bytes in https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus
100 // See [`note::WrappedNoteKey::zcash_deserialize`].
101 out_ciphertext: note::WrappedNoteKey::zcash_deserialize(&mut reader)?,
102 })
103 }
104}