docs: document consensus rules from 4.4 Spend Descriptions (#3460)
This commit is contained in:
parent
2f33300c08
commit
3bbb8f0531
|
@ -314,6 +314,8 @@ impl TryFrom<ValueCommitment> for NotSmallOrderValueCommitment {
|
||||||
///
|
///
|
||||||
/// Returns an error if the point is of small order.
|
/// Returns an error if the point is of small order.
|
||||||
///
|
///
|
||||||
|
/// # Consensus
|
||||||
|
///
|
||||||
/// > cv and rk [MUST NOT be of small order][1], i.e. [h_J]cv MUST NOT be 𝒪_J
|
/// > cv and rk [MUST NOT be of small order][1], i.e. [h_J]cv MUST NOT be 𝒪_J
|
||||||
/// > and [h_J]rk MUST NOT be 𝒪_J.
|
/// > and [h_J]rk MUST NOT be 𝒪_J.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1101,6 +1101,8 @@ impl TryFrom<redjubjub::VerificationKey<SpendAuth>> for ValidatingKey {
|
||||||
///
|
///
|
||||||
/// Returns an error if the key is malformed or [is of small order][1].
|
/// Returns an error if the key is malformed or [is of small order][1].
|
||||||
///
|
///
|
||||||
|
/// # Consensus
|
||||||
|
///
|
||||||
/// > Check that a Spend description's cv and rk are not of small order,
|
/// > Check that a Spend description's cv and rk are not of small order,
|
||||||
/// > i.e. [h_J]cv MUST NOT be 𝒪_J and [h_J]rk MUST NOT be 𝒪_J.
|
/// > i.e. [h_J]cv MUST NOT be 𝒪_J and [h_J]rk MUST NOT be 𝒪_J.
|
||||||
///
|
///
|
||||||
|
|
|
@ -186,15 +186,38 @@ impl ZcashDeserialize for Spend<PerSpendAnchor> {
|
||||||
///
|
///
|
||||||
/// The "anchor encoding for v4 transactions" is implemented here.
|
/// The "anchor encoding for v4 transactions" is implemented here.
|
||||||
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
|
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
|
||||||
|
// # Consensus
|
||||||
|
//
|
||||||
|
// > Elements of a Spend description MUST be valid encodings of the types given above.
|
||||||
|
//
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#spenddesc
|
||||||
|
//
|
||||||
|
// See comments below for each specific type.
|
||||||
Ok(Spend {
|
Ok(Spend {
|
||||||
|
// Type is `ValueCommit^{Sapling}.Output`, i.e. J
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#abstractcommit
|
||||||
|
// See [`commitment::NotSmallOrderValueCommitment::zcash_deserialize`].
|
||||||
cv: commitment::NotSmallOrderValueCommitment::zcash_deserialize(&mut reader)?,
|
cv: commitment::NotSmallOrderValueCommitment::zcash_deserialize(&mut reader)?,
|
||||||
|
// Type is `B^{[ℓ_{Sapling}_{Merkle}]}`, i.e. 32 bytes
|
||||||
per_spend_anchor: tree::Root(reader.read_32_bytes()?),
|
per_spend_anchor: tree::Root(reader.read_32_bytes()?),
|
||||||
|
// Type is `B^Y^{[ℓ_{PRFnfSapling}/8]}`, i.e. 32 bytes
|
||||||
nullifier: note::Nullifier::from(reader.read_32_bytes()?),
|
nullifier: note::Nullifier::from(reader.read_32_bytes()?),
|
||||||
|
// Type is `SpendAuthSig^{Sapling}.Public`, i.e. J
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#concretereddsa
|
||||||
|
// See [`ValidatingKey::try_from`].
|
||||||
rk: reader
|
rk: reader
|
||||||
.read_32_bytes()?
|
.read_32_bytes()?
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(SerializationError::Parse)?,
|
.map_err(SerializationError::Parse)?,
|
||||||
|
// Type is `ZKSpend.Proof`, described in
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#grothencoding
|
||||||
|
// It is not enforced here; this just reads 192 bytes.
|
||||||
|
// The type is validated when validating the proof, see
|
||||||
|
// [`groth16::Item::try_from`]. In #3179 we plan to validate here instead.
|
||||||
zkproof: Groth16Proof::zcash_deserialize(&mut reader)?,
|
zkproof: Groth16Proof::zcash_deserialize(&mut reader)?,
|
||||||
|
// Type is SpendAuthSig^{Sapling}.Signature, i.e.
|
||||||
|
// B^Y^{[ceiling(ℓ_G/8) + ceiling(bitlength(𝑟_G)/8)]} i.e. 64 bytes
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#concretereddsa
|
||||||
spend_auth_sig: reader.read_64_bytes()?.into(),
|
spend_auth_sig: reader.read_64_bytes()?.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -217,9 +240,23 @@ impl ZcashSerialize for SpendPrefixInTransactionV5 {
|
||||||
|
|
||||||
impl ZcashDeserialize for SpendPrefixInTransactionV5 {
|
impl ZcashDeserialize for SpendPrefixInTransactionV5 {
|
||||||
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
|
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
|
||||||
|
// # Consensus
|
||||||
|
//
|
||||||
|
// > Elements of a Spend description MUST be valid encodings of the types given above.
|
||||||
|
//
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#spenddesc
|
||||||
|
//
|
||||||
|
// See comments below for each specific type.
|
||||||
Ok(SpendPrefixInTransactionV5 {
|
Ok(SpendPrefixInTransactionV5 {
|
||||||
|
// Type is `ValueCommit^{Sapling}.Output`, i.e. J
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#abstractcommit
|
||||||
|
// See [`commitment::NotSmallOrderValueCommitment::zcash_deserialize`].
|
||||||
cv: commitment::NotSmallOrderValueCommitment::zcash_deserialize(&mut reader)?,
|
cv: commitment::NotSmallOrderValueCommitment::zcash_deserialize(&mut reader)?,
|
||||||
|
// Type is `B^Y^{[ℓ_{PRFnfSapling}/8]}`, i.e. 32 bytes
|
||||||
nullifier: note::Nullifier::from(reader.read_32_bytes()?),
|
nullifier: note::Nullifier::from(reader.read_32_bytes()?),
|
||||||
|
// Type is `SpendAuthSig^{Sapling}.Public`, i.e. J
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#concretereddsa
|
||||||
|
// See [`ValidatingKey::try_from`].
|
||||||
rk: reader
|
rk: reader
|
||||||
.read_32_bytes()?
|
.read_32_bytes()?
|
||||||
.try_into()
|
.try_into()
|
||||||
|
|
|
@ -191,6 +191,14 @@ impl ZcashDeserialize for Option<sapling::ShieldedData<SharedAnchor>> {
|
||||||
let value_balance = (&mut reader).zcash_deserialize_into()?;
|
let value_balance = (&mut reader).zcash_deserialize_into()?;
|
||||||
|
|
||||||
// anchorSapling
|
// anchorSapling
|
||||||
|
//
|
||||||
|
// # Consensus
|
||||||
|
//
|
||||||
|
// > Elements of a Spend description MUST be valid encodings of the types given above.
|
||||||
|
//
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#spenddesc
|
||||||
|
//
|
||||||
|
// Type is `B^{[ℓ_{Sapling}_{Merkle}]}`, i.e. 32 bytes
|
||||||
let shared_anchor = if spends_count > 0 {
|
let shared_anchor = if spends_count > 0 {
|
||||||
Some(reader.read_32_bytes()?.into())
|
Some(reader.read_32_bytes()?.into())
|
||||||
} else {
|
} else {
|
||||||
|
@ -198,8 +206,32 @@ impl ZcashDeserialize for Option<sapling::ShieldedData<SharedAnchor>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// vSpendProofsSapling
|
// vSpendProofsSapling
|
||||||
|
//
|
||||||
|
// # Consensus
|
||||||
|
//
|
||||||
|
// > Elements of a Spend description MUST be valid encodings of the types given above.
|
||||||
|
//
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#spenddesc
|
||||||
|
//
|
||||||
|
// Type is `ZKSpend.Proof`, described in
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#grothencoding
|
||||||
|
// It is not enforced here; this just reads 192 bytes.
|
||||||
|
// The type is validated when validating the proof, see
|
||||||
|
// [`groth16::Item::try_from`]. In #3179 we plan to validate here instead.
|
||||||
let spend_proofs = zcash_deserialize_external_count(spends_count, &mut reader)?;
|
let spend_proofs = zcash_deserialize_external_count(spends_count, &mut reader)?;
|
||||||
|
|
||||||
// vSpendAuthSigsSapling
|
// vSpendAuthSigsSapling
|
||||||
|
//
|
||||||
|
// # Consensus
|
||||||
|
//
|
||||||
|
// > Elements of a Spend description MUST be valid encodings of the types given above.
|
||||||
|
//
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#spenddesc
|
||||||
|
//
|
||||||
|
// Type is SpendAuthSig^{Sapling}.Signature, i.e.
|
||||||
|
// B^Y^{[ceiling(ℓ_G/8) + ceiling(bitlength(𝑟_G)/8)]} i.e. 64 bytes
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#concretereddsa
|
||||||
|
// See [`redjubjub::Signature<SpendAuth>::zcash_deserialize`].
|
||||||
let spend_sigs = zcash_deserialize_external_count(spends_count, &mut reader)?;
|
let spend_sigs = zcash_deserialize_external_count(spends_count, &mut reader)?;
|
||||||
|
|
||||||
// vOutputProofsSapling
|
// vOutputProofsSapling
|
||||||
|
|
|
@ -763,9 +763,13 @@ where
|
||||||
|
|
||||||
if let Some(sapling_shielded_data) = sapling_shielded_data {
|
if let Some(sapling_shielded_data) = sapling_shielded_data {
|
||||||
for spend in sapling_shielded_data.spends_per_anchor() {
|
for spend in sapling_shielded_data.spends_per_anchor() {
|
||||||
// Consensus rule: The proof π_ZKSpend MUST be valid
|
// # Consensus
|
||||||
// given a primary input formed from the other
|
//
|
||||||
// fields except spendAuthSig.
|
// > The proof π_ZKSpend MUST be valid
|
||||||
|
// > given a primary input formed from the other
|
||||||
|
// > fields except spendAuthSig.
|
||||||
|
//
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#spenddesc
|
||||||
//
|
//
|
||||||
// Queue the verification of the Groth16 spend proof
|
// Queue the verification of the Groth16 spend proof
|
||||||
// for each Spend description while adding the
|
// for each Spend description while adding the
|
||||||
|
@ -778,9 +782,23 @@ where
|
||||||
.oneshot(DescriptionWrapper(&spend).try_into()?),
|
.oneshot(DescriptionWrapper(&spend).try_into()?),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Consensus rule: The spend authorization signature
|
// # Consensus
|
||||||
// MUST be a valid SpendAuthSig signature over
|
//
|
||||||
// SigHash using rk as the validating key.
|
// > The spend authorization signature
|
||||||
|
// > MUST be a valid SpendAuthSig signature over
|
||||||
|
// > SigHash using rk as the validating key.
|
||||||
|
//
|
||||||
|
// This is validated by the verifier.
|
||||||
|
//
|
||||||
|
// > [NU5 onward] As specified in § 5.4.7 ‘RedDSA, RedJubjub,
|
||||||
|
// > and RedPallas’ on p. 88, the validation of the 𝑅
|
||||||
|
// > component of the signature changes to prohibit non-canonical encodings.
|
||||||
|
//
|
||||||
|
// This is validated by the verifier, inside the `redjubjub` crate.
|
||||||
|
// It calls [`jubjub::AffinePoint::from_bytes`] to parse R and
|
||||||
|
// that enforces the canonical encoding.
|
||||||
|
//
|
||||||
|
// https://zips.z.cash/protocol/protocol.pdf#spenddesc
|
||||||
//
|
//
|
||||||
// Queue the validation of the RedJubjub spend
|
// Queue the validation of the RedJubjub spend
|
||||||
// authorization signature for each Spend
|
// authorization signature for each Spend
|
||||||
|
|
Loading…
Reference in New Issue