diff --git a/zcash_primitives/src/serialize.rs b/zcash_primitives/src/serialize.rs index 37315d209..267c5c1f5 100644 --- a/zcash_primitives/src/serialize.rs +++ b/zcash_primitives/src/serialize.rs @@ -1,4 +1,5 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use nonempty::NonEmpty; use std::io::{self, Read, Write}; const MAX_SIZE: usize = 0x02000000; @@ -80,6 +81,18 @@ impl Vector { CompactSize::write(&mut writer, vec.len())?; vec.iter().try_for_each(|e| func(&mut writer, e)) } + + pub fn write_nonempty( + mut writer: W, + vec: &NonEmpty, + func: F, + ) -> io::Result<()> + where + F: Fn(&mut W, &E) -> io::Result<()>, + { + CompactSize::write(&mut writer, vec.len())?; + vec.iter().try_for_each(|e| func(&mut writer, e)) + } } pub struct Array; diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 5f2efe110..1e6649600 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -680,10 +680,10 @@ impl Transaction { fn read_v5_sapling( mut reader: R, ) -> io::Result>> { - let n_spends = CompactSize::read(&mut reader)?; - let sd_v5s = Array::read(&mut reader, n_spends, SpendDescriptionV5::read)?; - let n_outputs = CompactSize::read(&mut reader)?; - let od_v5s = Array::read(&mut reader, n_outputs, OutputDescriptionV5::read)?; + let sd_v5s = Vector::read(&mut reader, SpendDescriptionV5::read)?; + let od_v5s = Vector::read(&mut reader, OutputDescriptionV5::read)?; + let n_spends = sd_v5s.len(); + let n_outputs = od_v5s.len(); let value_balance = if n_spends > 0 || n_outputs > 0 { Self::read_amount(&mut reader)? } else { @@ -738,33 +738,22 @@ impl Transaction { fn read_v5_orchard( mut reader: R, ) -> io::Result>> { - let n_actions = CompactSize::read(&mut reader)?; - if n_actions == 0 { + let actions_without_auth = Vector::read(&mut reader, |r| { + orchard_serialization::read_action_without_auth(r) + })?; + if actions_without_auth.is_empty() { Ok(None) } else { - let actions_without_auth = Array::read(&mut reader, n_actions, |r| { - orchard_serialization::read_action_without_auth(r) - })?; + let n_actions = actions_without_auth.len(); let flags = orchard_serialization::read_flags(&mut reader)?; let value_balance = Self::read_amount(&mut reader)?; let anchor = orchard_serialization::read_anchor(&mut reader)?; - let proof_size = CompactSize::read(&mut reader)?; - let mut proof_bytes = vec![0u8; proof_size]; - reader.read_exact(&mut proof_bytes)?; + let proof_bytes = Vector::read(&mut reader, |r| r.read_u8())?; let spend_sigs = Array::read(&mut reader, n_actions, |r| { orchard_serialization::read_signature::<_, redpallas::SpendAuth>(r) })?; let binding_signature = - orchard_serialization::read_signature::<_, redpallas::Binding>(&mut reader) - .map_err(|e| { - io::Error::new( - io::ErrorKind::InvalidInput, - format!( - "An error occurred deserializing the Orchard binding signature: {}", - e - ), - ) - })?; + orchard_serialization::read_signature::<_, redpallas::Binding>(&mut reader)?; let actions = NonEmpty::from_vec( actions_without_auth @@ -912,13 +901,11 @@ impl Transaction { pub fn write_v5_sapling(&self, mut writer: W) -> io::Result<()> { if let Some(bundle) = &self.sapling_bundle { - CompactSize::write(&mut writer, bundle.shielded_spends.len())?; - Array::write(&mut writer, &bundle.shielded_spends, |w, e| { + Vector::write(&mut writer, &bundle.shielded_spends, |w, e| { e.write_v5_without_witness_data(w) })?; - CompactSize::write(&mut writer, bundle.shielded_outputs.len())?; - Array::write(&mut writer, &bundle.shielded_outputs, |w, e| { + Vector::write(&mut writer, &bundle.shielded_outputs, |w, e| { e.write_v5_without_proof(w) })?; @@ -959,8 +946,7 @@ impl Transaction { pub fn write_v5_orchard(&self, mut writer: W) -> io::Result<()> { if let Some(bundle) = &self.orchard_bundle { - CompactSize::write(&mut writer, bundle.actions().len())?; - Array::write(&mut writer, bundle.actions().iter(), |w, a| { + Vector::write_nonempty(&mut writer, bundle.actions(), |w, a| { orchard_serialization::write_action_without_auth(w, a) })?; @@ -968,9 +954,11 @@ impl Transaction { orchard_serialization::write_flags(&mut writer, &bundle.flags())?; writer.write_all(&bundle.value_balance().to_i64_le_bytes())?; orchard_serialization::write_anchor(&mut writer, bundle.anchor())?; - let proof_bytes: &[u8] = bundle.authorization().proof().as_ref(); - CompactSize::write(&mut writer, proof_bytes.len())?; - writer.write_all(&proof_bytes)?; + Vector::write( + &mut writer, + bundle.authorization().proof().as_ref(), + |w, b| w.write_u8(*b), + )?; Array::write( &mut writer, bundle.actions().iter().map(|a| a.authorization()),