zcash_primitives: Rework Sapling parsers to be plain functions
Once `zcash_primitives::sapling` is extracted to `sapling-crypto`, these would have become orphan impls.
This commit is contained in:
parent
54eb03e34e
commit
e1a5539094
|
@ -124,6 +124,13 @@ and this library adheres to Rust's notion of
|
|||
### Removed
|
||||
- `zcash_primitives::constants`:
|
||||
- All `const` values (moved to `zcash_primitives::sapling::constants`).
|
||||
- `zcash_primitives::sapling::bundle`:
|
||||
- `SpendDescription::{read, read_nullifier, read_rk, read_spend_auth_sig}`
|
||||
- `SpendDescription::{write_v4, write_v5_without_witness_data}`
|
||||
- `SpendDescriptionV5::read`
|
||||
- `OutputDescription::read`
|
||||
- `OutputDescription::{write_v4, write_v5_without_proof}`
|
||||
- `OutputDescriptionV5::read`
|
||||
- `zcash_primitives::transaction::components::sapling`:
|
||||
- The following types were removed from this module (moved into
|
||||
`zcash_primitives::sapling::bundle`):
|
||||
|
|
|
@ -68,153 +68,159 @@ pub fn read_zkproof<R: Read>(mut reader: R) -> io::Result<GrothProofBytes> {
|
|||
Ok(zkproof)
|
||||
}
|
||||
|
||||
impl SpendDescription<Authorized> {
|
||||
pub fn read_nullifier<R: Read>(mut reader: R) -> io::Result<Nullifier> {
|
||||
let mut nullifier = Nullifier([0u8; 32]);
|
||||
reader.read_exact(&mut nullifier.0)?;
|
||||
Ok(nullifier)
|
||||
}
|
||||
|
||||
/// Consensus rules (§4.4):
|
||||
/// - Canonical encoding is enforced here.
|
||||
/// - "Not small order" is enforced in SaplingVerificationContext::check_spend()
|
||||
pub fn read_rk<R: Read>(mut reader: R) -> io::Result<PublicKey> {
|
||||
PublicKey::read(&mut reader)
|
||||
}
|
||||
|
||||
/// Consensus rules (§4.4):
|
||||
/// - Canonical encoding is enforced here.
|
||||
/// - Signature validity is enforced in SaplingVerificationContext::check_spend()
|
||||
pub fn read_spend_auth_sig<R: Read>(mut reader: R) -> io::Result<Signature> {
|
||||
Signature::read(&mut reader)
|
||||
}
|
||||
|
||||
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
||||
// Consensus rules (§4.4) & (§4.5):
|
||||
// - Canonical encoding is enforced here.
|
||||
// - "Not small order" is enforced in SaplingVerificationContext::(check_spend()/check_output())
|
||||
// (located in zcash_proofs::sapling::verifier).
|
||||
let cv = read_value_commitment(&mut reader)?;
|
||||
// Consensus rules (§7.3) & (§7.4):
|
||||
// - Canonical encoding is enforced here
|
||||
let anchor = read_base(&mut reader, "anchor")?;
|
||||
let nullifier = Self::read_nullifier(&mut reader)?;
|
||||
let rk = Self::read_rk(&mut reader)?;
|
||||
let zkproof = read_zkproof(&mut reader)?;
|
||||
let spend_auth_sig = Self::read_spend_auth_sig(&mut reader)?;
|
||||
|
||||
Ok(SpendDescription::from_parts(
|
||||
cv,
|
||||
anchor,
|
||||
nullifier,
|
||||
rk,
|
||||
zkproof,
|
||||
spend_auth_sig,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn write_v4<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
writer.write_all(&self.cv().to_bytes())?;
|
||||
writer.write_all(self.anchor().to_repr().as_ref())?;
|
||||
writer.write_all(&self.nullifier().0)?;
|
||||
self.rk().write(&mut writer)?;
|
||||
writer.write_all(self.zkproof())?;
|
||||
self.spend_auth_sig().write(&mut writer)
|
||||
}
|
||||
|
||||
pub fn write_v5_without_witness_data<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
writer.write_all(&self.cv().to_bytes())?;
|
||||
writer.write_all(&self.nullifier().0)?;
|
||||
self.rk().write(&mut writer)
|
||||
}
|
||||
pub(crate) fn read_nullifier<R: Read>(mut reader: R) -> io::Result<Nullifier> {
|
||||
let mut nullifier = Nullifier([0u8; 32]);
|
||||
reader.read_exact(&mut nullifier.0)?;
|
||||
Ok(nullifier)
|
||||
}
|
||||
|
||||
impl SpendDescriptionV5 {
|
||||
pub fn read<R: Read>(mut reader: &mut R) -> io::Result<Self> {
|
||||
let cv = read_value_commitment(&mut reader)?;
|
||||
let nullifier = SpendDescription::read_nullifier(&mut reader)?;
|
||||
let rk = SpendDescription::read_rk(&mut reader)?;
|
||||
|
||||
Ok(SpendDescriptionV5::from_parts(cv, nullifier, rk))
|
||||
}
|
||||
/// Consensus rules (§4.4):
|
||||
/// - Canonical encoding is enforced here.
|
||||
/// - "Not small order" is enforced in SaplingVerificationContext::check_spend()
|
||||
pub(crate) fn read_rk<R: Read>(mut reader: R) -> io::Result<PublicKey> {
|
||||
PublicKey::read(&mut reader)
|
||||
}
|
||||
|
||||
impl OutputDescription<GrothProofBytes> {
|
||||
pub fn read<R: Read>(mut reader: &mut R) -> io::Result<Self> {
|
||||
// Consensus rules (§4.5):
|
||||
// - Canonical encoding is enforced here.
|
||||
// - "Not small order" is enforced in SaplingVerificationContext::check_output()
|
||||
// (located in zcash_proofs::sapling::verifier).
|
||||
let cv = read_value_commitment(&mut reader)?;
|
||||
|
||||
// Consensus rule (§7.4): Canonical encoding is enforced here
|
||||
let cmu = read_cmu(&mut reader)?;
|
||||
|
||||
// Consensus rules (§4.5):
|
||||
// - Canonical encoding is enforced in librustzcash_sapling_check_output by zcashd
|
||||
// - "Not small order" is enforced in SaplingVerificationContext::check_output()
|
||||
let mut ephemeral_key = EphemeralKeyBytes([0u8; 32]);
|
||||
reader.read_exact(&mut ephemeral_key.0)?;
|
||||
|
||||
let mut enc_ciphertext = [0u8; 580];
|
||||
let mut out_ciphertext = [0u8; 80];
|
||||
reader.read_exact(&mut enc_ciphertext)?;
|
||||
reader.read_exact(&mut out_ciphertext)?;
|
||||
|
||||
let zkproof = read_zkproof(&mut reader)?;
|
||||
|
||||
Ok(OutputDescription::from_parts(
|
||||
cv,
|
||||
cmu,
|
||||
ephemeral_key,
|
||||
enc_ciphertext,
|
||||
out_ciphertext,
|
||||
zkproof,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn write_v4<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
writer.write_all(&self.cv().to_bytes())?;
|
||||
writer.write_all(self.cmu().to_bytes().as_ref())?;
|
||||
writer.write_all(self.ephemeral_key().as_ref())?;
|
||||
writer.write_all(self.enc_ciphertext())?;
|
||||
writer.write_all(self.out_ciphertext())?;
|
||||
writer.write_all(self.zkproof())
|
||||
}
|
||||
|
||||
pub fn write_v5_without_proof<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
writer.write_all(&self.cv().to_bytes())?;
|
||||
writer.write_all(self.cmu().to_bytes().as_ref())?;
|
||||
writer.write_all(self.ephemeral_key().as_ref())?;
|
||||
writer.write_all(self.enc_ciphertext())?;
|
||||
writer.write_all(self.out_ciphertext())
|
||||
}
|
||||
/// Consensus rules (§4.4):
|
||||
/// - Canonical encoding is enforced here.
|
||||
/// - Signature validity is enforced in SaplingVerificationContext::check_spend()
|
||||
pub(crate) fn read_spend_auth_sig<R: Read>(mut reader: R) -> io::Result<Signature> {
|
||||
Signature::read(&mut reader)
|
||||
}
|
||||
|
||||
impl OutputDescriptionV5 {
|
||||
pub fn read<R: Read>(mut reader: &mut R) -> io::Result<Self> {
|
||||
let cv = read_value_commitment(&mut reader)?;
|
||||
let cmu = read_cmu(&mut reader)?;
|
||||
pub(crate) fn read_spend_v4<R: Read>(mut reader: R) -> io::Result<SpendDescription<Authorized>> {
|
||||
// Consensus rules (§4.4) & (§4.5):
|
||||
// - Canonical encoding is enforced here.
|
||||
// - "Not small order" is enforced in SaplingVerificationContext::(check_spend()/check_output())
|
||||
// (located in zcash_proofs::sapling::verifier).
|
||||
let cv = read_value_commitment(&mut reader)?;
|
||||
// Consensus rules (§7.3) & (§7.4):
|
||||
// - Canonical encoding is enforced here
|
||||
let anchor = read_base(&mut reader, "anchor")?;
|
||||
let nullifier = read_nullifier(&mut reader)?;
|
||||
let rk = read_rk(&mut reader)?;
|
||||
let zkproof = read_zkproof(&mut reader)?;
|
||||
let spend_auth_sig = read_spend_auth_sig(&mut reader)?;
|
||||
|
||||
// Consensus rules (§4.5):
|
||||
// - Canonical encoding is enforced in librustzcash_sapling_check_output by zcashd
|
||||
// - "Not small order" is enforced in SaplingVerificationContext::check_output()
|
||||
let mut ephemeral_key = EphemeralKeyBytes([0u8; 32]);
|
||||
reader.read_exact(&mut ephemeral_key.0)?;
|
||||
Ok(SpendDescription::from_parts(
|
||||
cv,
|
||||
anchor,
|
||||
nullifier,
|
||||
rk,
|
||||
zkproof,
|
||||
spend_auth_sig,
|
||||
))
|
||||
}
|
||||
|
||||
let mut enc_ciphertext = [0u8; 580];
|
||||
let mut out_ciphertext = [0u8; 80];
|
||||
reader.read_exact(&mut enc_ciphertext)?;
|
||||
reader.read_exact(&mut out_ciphertext)?;
|
||||
pub(crate) fn write_spend_v4<W: Write>(
|
||||
mut writer: W,
|
||||
spend: &SpendDescription<Authorized>,
|
||||
) -> io::Result<()> {
|
||||
writer.write_all(&spend.cv().to_bytes())?;
|
||||
writer.write_all(spend.anchor().to_repr().as_ref())?;
|
||||
writer.write_all(&spend.nullifier().0)?;
|
||||
spend.rk().write(&mut writer)?;
|
||||
writer.write_all(spend.zkproof())?;
|
||||
spend.spend_auth_sig().write(&mut writer)
|
||||
}
|
||||
|
||||
Ok(OutputDescriptionV5::from_parts(
|
||||
cv,
|
||||
cmu,
|
||||
ephemeral_key,
|
||||
enc_ciphertext,
|
||||
out_ciphertext,
|
||||
))
|
||||
}
|
||||
pub(crate) fn write_spend_v5_without_witness_data<W: Write>(
|
||||
mut writer: W,
|
||||
spend: &SpendDescription<Authorized>,
|
||||
) -> io::Result<()> {
|
||||
writer.write_all(&spend.cv().to_bytes())?;
|
||||
writer.write_all(&spend.nullifier().0)?;
|
||||
spend.rk().write(&mut writer)
|
||||
}
|
||||
|
||||
pub(crate) fn read_spend_v5<R: Read>(mut reader: &mut R) -> io::Result<SpendDescriptionV5> {
|
||||
let cv = read_value_commitment(&mut reader)?;
|
||||
let nullifier = read_nullifier(&mut reader)?;
|
||||
let rk = read_rk(&mut reader)?;
|
||||
|
||||
Ok(SpendDescriptionV5::from_parts(cv, nullifier, rk))
|
||||
}
|
||||
|
||||
pub(crate) fn read_output_v4<R: Read>(
|
||||
mut reader: &mut R,
|
||||
) -> io::Result<OutputDescription<GrothProofBytes>> {
|
||||
// Consensus rules (§4.5):
|
||||
// - Canonical encoding is enforced here.
|
||||
// - "Not small order" is enforced in SaplingVerificationContext::check_output()
|
||||
// (located in zcash_proofs::sapling::verifier).
|
||||
let cv = read_value_commitment(&mut reader)?;
|
||||
|
||||
// Consensus rule (§7.4): Canonical encoding is enforced here
|
||||
let cmu = read_cmu(&mut reader)?;
|
||||
|
||||
// Consensus rules (§4.5):
|
||||
// - Canonical encoding is enforced in librustzcash_sapling_check_output by zcashd
|
||||
// - "Not small order" is enforced in SaplingVerificationContext::check_output()
|
||||
let mut ephemeral_key = EphemeralKeyBytes([0u8; 32]);
|
||||
reader.read_exact(&mut ephemeral_key.0)?;
|
||||
|
||||
let mut enc_ciphertext = [0u8; 580];
|
||||
let mut out_ciphertext = [0u8; 80];
|
||||
reader.read_exact(&mut enc_ciphertext)?;
|
||||
reader.read_exact(&mut out_ciphertext)?;
|
||||
|
||||
let zkproof = read_zkproof(&mut reader)?;
|
||||
|
||||
Ok(OutputDescription::from_parts(
|
||||
cv,
|
||||
cmu,
|
||||
ephemeral_key,
|
||||
enc_ciphertext,
|
||||
out_ciphertext,
|
||||
zkproof,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn write_output_v4<W: Write>(
|
||||
mut writer: W,
|
||||
output: &OutputDescription<GrothProofBytes>,
|
||||
) -> io::Result<()> {
|
||||
writer.write_all(&output.cv().to_bytes())?;
|
||||
writer.write_all(output.cmu().to_bytes().as_ref())?;
|
||||
writer.write_all(output.ephemeral_key().as_ref())?;
|
||||
writer.write_all(output.enc_ciphertext())?;
|
||||
writer.write_all(output.out_ciphertext())?;
|
||||
writer.write_all(output.zkproof())
|
||||
}
|
||||
|
||||
pub(crate) fn write_output_v5_without_proof<W: Write>(
|
||||
mut writer: W,
|
||||
output: &OutputDescription<GrothProofBytes>,
|
||||
) -> io::Result<()> {
|
||||
writer.write_all(&output.cv().to_bytes())?;
|
||||
writer.write_all(output.cmu().to_bytes().as_ref())?;
|
||||
writer.write_all(output.ephemeral_key().as_ref())?;
|
||||
writer.write_all(output.enc_ciphertext())?;
|
||||
writer.write_all(output.out_ciphertext())
|
||||
}
|
||||
|
||||
pub(crate) fn read_output_v5<R: Read>(mut reader: &mut R) -> io::Result<OutputDescriptionV5> {
|
||||
let cv = read_value_commitment(&mut reader)?;
|
||||
let cmu = read_cmu(&mut reader)?;
|
||||
|
||||
// Consensus rules (§4.5):
|
||||
// - Canonical encoding is enforced in librustzcash_sapling_check_output by zcashd
|
||||
// - "Not small order" is enforced in SaplingVerificationContext::check_output()
|
||||
let mut ephemeral_key = EphemeralKeyBytes([0u8; 32]);
|
||||
reader.read_exact(&mut ephemeral_key.0)?;
|
||||
|
||||
let mut enc_ciphertext = [0u8; 580];
|
||||
let mut out_ciphertext = [0u8; 80];
|
||||
reader.read_exact(&mut enc_ciphertext)?;
|
||||
reader.read_exact(&mut out_ciphertext)?;
|
||||
|
||||
Ok(OutputDescriptionV5::from_parts(
|
||||
cv,
|
||||
cmu,
|
||||
ephemeral_key,
|
||||
enc_ciphertext,
|
||||
out_ciphertext,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-dependencies"))]
|
||||
|
|
|
@ -26,7 +26,7 @@ use crate::{
|
|||
consensus::{BlockHeight, BranchId},
|
||||
sapling::{
|
||||
self, builder as sapling_builder,
|
||||
bundle::{OutputDescription, OutputDescriptionV5, SpendDescription, SpendDescriptionV5},
|
||||
bundle::{OutputDescription, SpendDescription},
|
||||
redjubjub,
|
||||
},
|
||||
};
|
||||
|
@ -606,10 +606,10 @@ impl Transaction {
|
|||
let vb = Self::read_amount(&mut reader)?;
|
||||
#[allow(clippy::redundant_closure)]
|
||||
let ss: Vec<SpendDescription<sapling::bundle::Authorized>> =
|
||||
Vector::read(&mut reader, |r| SpendDescription::read(r))?;
|
||||
Vector::read(&mut reader, |r| sapling_serialization::read_spend_v4(r))?;
|
||||
#[allow(clippy::redundant_closure)]
|
||||
let so: Vec<OutputDescription<sapling::bundle::GrothProofBytes>> =
|
||||
Vector::read(&mut reader, |r| OutputDescription::read(r))?;
|
||||
Vector::read(&mut reader, |r| sapling_serialization::read_output_v4(r))?;
|
||||
(vb, ss, so)
|
||||
} else {
|
||||
(Amount::zero(), vec![], vec![])
|
||||
|
@ -750,8 +750,8 @@ impl Transaction {
|
|||
fn read_v5_sapling<R: Read>(
|
||||
mut reader: R,
|
||||
) -> io::Result<Option<sapling::Bundle<sapling::bundle::Authorized>>> {
|
||||
let sd_v5s = Vector::read(&mut reader, SpendDescriptionV5::read)?;
|
||||
let od_v5s = Vector::read(&mut reader, OutputDescriptionV5::read)?;
|
||||
let sd_v5s = Vector::read(&mut reader, sapling_serialization::read_spend_v5)?;
|
||||
let od_v5s = Vector::read(&mut reader, sapling_serialization::read_output_v5)?;
|
||||
let n_spends = sd_v5s.len();
|
||||
let n_outputs = od_v5s.len();
|
||||
let value_balance = if n_spends > 0 || n_outputs > 0 {
|
||||
|
@ -770,7 +770,7 @@ impl Transaction {
|
|||
sapling_serialization::read_zkproof(r)
|
||||
})?;
|
||||
let v_spend_auth_sigs = Array::read(&mut reader, n_spends, |r| {
|
||||
SpendDescription::read_spend_auth_sig(r)
|
||||
sapling_serialization::read_spend_auth_sig(r)
|
||||
})?;
|
||||
let v_output_proofs = Array::read(&mut reader, n_outputs, |r| {
|
||||
sapling_serialization::read_zkproof(r)
|
||||
|
@ -859,14 +859,14 @@ impl Transaction {
|
|||
self.sapling_bundle
|
||||
.as_ref()
|
||||
.map_or(&[], |b| b.shielded_spends()),
|
||||
|w, e| e.write_v4(w),
|
||||
|w, e| sapling_serialization::write_spend_v4(w, e),
|
||||
)?;
|
||||
Vector::write(
|
||||
&mut writer,
|
||||
self.sapling_bundle
|
||||
.as_ref()
|
||||
.map_or(&[], |b| b.shielded_outputs()),
|
||||
|w, e| e.write_v4(w),
|
||||
|w, e| sapling_serialization::write_output_v4(w, e),
|
||||
)?;
|
||||
} else if self.sapling_bundle.is_some() {
|
||||
return Err(io::Error::new(
|
||||
|
@ -955,11 +955,11 @@ impl Transaction {
|
|||
) -> io::Result<()> {
|
||||
if let Some(bundle) = sapling_bundle {
|
||||
Vector::write(&mut writer, bundle.shielded_spends(), |w, e| {
|
||||
e.write_v5_without_witness_data(w)
|
||||
sapling_serialization::write_spend_v5_without_witness_data(w, e)
|
||||
})?;
|
||||
|
||||
Vector::write(&mut writer, bundle.shielded_outputs(), |w, e| {
|
||||
e.write_v5_without_proof(w)
|
||||
sapling_serialization::write_output_v5_without_proof(w, e)
|
||||
})?;
|
||||
|
||||
if !(bundle.shielded_spends().is_empty() && bundle.shielded_outputs().is_empty()) {
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::{
|
|||
|
||||
use super::{
|
||||
components::{
|
||||
sapling as sapling_serialization,
|
||||
sprout::JsDescription,
|
||||
transparent::{self, TxIn, TxOut},
|
||||
},
|
||||
|
@ -123,7 +124,7 @@ fn shielded_spends_hash<
|
|||
fn shielded_outputs_hash(shielded_outputs: &[OutputDescription<GrothProofBytes>]) -> Blake2bHash {
|
||||
let mut data = Vec::with_capacity(shielded_outputs.len() * 948);
|
||||
for s_out in shielded_outputs {
|
||||
s_out.write_v4(&mut data).unwrap();
|
||||
sapling_serialization::write_output_v4(&mut data, s_out).unwrap();
|
||||
}
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
|
|
Loading…
Reference in New Issue