Add `zcash_encoding::{CompactSize, Vector}::serialized_size` and

`zcash_primitives::legacy::Script::serialized_size`. Use the latter in
`zcash_primitives::transaction::fees::transparent::OutputView::serialized_size`.

Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira-Emma Hopwood 2024-06-18 21:06:39 +01:00
parent 17af8e32e8
commit 9881861228
5 changed files with 40 additions and 7 deletions

View File

@ -6,6 +6,9 @@ and this library adheres to Rust's notion of
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [Unreleased]
### Added
- `zcash_encoding::CompactSize::serialized_size`
- `zcash_encoding::Vector::serialized_size`
## [0.2.0] - 2022-10-19 ## [0.2.0] - 2022-10-19
### Changed ### Changed

View File

@ -93,6 +93,16 @@ impl CompactSize {
} }
} }
} }
/// Returns the number of bytes needed to encode the given size in compact form.
pub fn serialized_size(size: usize) -> usize {
match size {
s if s < 253 => 1,
s if s <= 0xFFFF => 3,
s if s <= 0xFFFFFFFF => 5,
_ => 9,
}
}
} }
/// Namespace for functions that perform encoding of vectors. /// Namespace for functions that perform encoding of vectors.
@ -171,6 +181,12 @@ impl Vector {
CompactSize::write(&mut writer, items.len())?; CompactSize::write(&mut writer, items.len())?;
items.try_for_each(|e| func(&mut writer, e)) items.try_for_each(|e| func(&mut writer, e))
} }
/// Returns the serialized size of a vector of `u8` as written by `[Vector::write]`.
pub fn serialized_size(vec: &[u8]) -> usize {
let length = vec.len();
CompactSize::serialized_size(length) + length
}
} }
/// Namespace for functions that perform encoding of array contents. /// Namespace for functions that perform encoding of array contents.
@ -279,8 +295,11 @@ mod tests {
<T as TryInto<usize>>::Error: Debug, <T as TryInto<usize>>::Error: Debug,
{ {
let mut data = vec![]; let mut data = vec![];
CompactSize::write(&mut data, value.try_into().unwrap()).unwrap(); let value_usize: usize = value.try_into().unwrap();
CompactSize::write(&mut data, value_usize).unwrap();
assert_eq!(&data[..], expected); assert_eq!(&data[..], expected);
let serialized_size = CompactSize::serialized_size(value_usize);
assert_eq!(serialized_size, expected.len());
let result: io::Result<T> = CompactSize::read_t(&data[..]); let result: io::Result<T> = CompactSize::read_t(&data[..]);
match result { match result {
Ok(n) => assert_eq!(n, value), Ok(n) => assert_eq!(n, value),
@ -308,6 +327,8 @@ mod tests {
let mut data = vec![]; let mut data = vec![];
CompactSize::write(&mut data, value).unwrap(); CompactSize::write(&mut data, value).unwrap();
assert_eq!(&data[..], encoded); assert_eq!(&data[..], encoded);
let serialized_size = CompactSize::serialized_size(value);
assert_eq!(serialized_size, encoded.len());
assert!(CompactSize::read(encoded).is_err()); assert!(CompactSize::read(encoded).is_err());
} }
} }
@ -320,6 +341,8 @@ mod tests {
let mut data = vec![]; let mut data = vec![];
Vector::write(&mut data, &$value, |w, e| w.write_u8(*e)).unwrap(); Vector::write(&mut data, &$value, |w, e| w.write_u8(*e)).unwrap();
assert_eq!(&data[..], &$expected[..]); assert_eq!(&data[..], &$expected[..]);
let serialized_size = Vector::serialized_size(&$value);
assert_eq!(serialized_size, $expected.len());
match Vector::read(&data[..], |r| r.read_u8()) { match Vector::read(&data[..], |r| r.read_u8()) {
Ok(v) => assert_eq!(v, $value), Ok(v) => assert_eq!(v, $value),
Err(e) => panic!("Unexpected error: {:?}", e), Err(e) => panic!("Unexpected error: {:?}", e),

View File

@ -11,6 +11,11 @@ and this library adheres to Rust's notion of
- `impl From<TransparentKeyScope> for bip32::ChildNumber` - `impl From<TransparentKeyScope> for bip32::ChildNumber`
- `impl From<NonHardenedChildIndex> for bip32::ChildNumber` - `impl From<NonHardenedChildIndex> for bip32::ChildNumber`
- `impl TryFrom<bip32::ChildNumber> for NonHardenedChildIndex` - `impl TryFrom<bip32::ChildNumber> for NonHardenedChildIndex`
- `zcash_primitives::legacy::Script::serialized_size`
- `zcash_primitives::transaction::fees::transparent`:
- `InputSize`
- `InputView::serialized_size`
- `OutputView::serialized_size`
### Changed ### Changed
- MSRV is now 1.70.0. - MSRV is now 1.70.0.

View File

@ -322,6 +322,11 @@ impl Script {
Vector::write(&mut writer, &self.0, |w, e| w.write_u8(*e)) Vector::write(&mut writer, &self.0, |w, e| w.write_u8(*e))
} }
/// Returns the length of this script as encoded (including the initial CompactSize).
pub fn serialized_size(&self) -> usize {
Vector::serialized_size(&self.0)
}
/// Returns the address that this Script contains, if any. /// Returns the address that this Script contains, if any.
pub(crate) fn address(&self) -> Option<TransparentAddress> { pub(crate) fn address(&self) -> Option<TransparentAddress> {
if self.0.len() == 25 if self.0.len() == 25

View File

@ -77,12 +77,9 @@ pub trait OutputView: std::fmt::Debug {
/// Returns the serialized size of the txout. /// Returns the serialized size of the txout.
fn serialized_size(&self) -> usize { fn serialized_size(&self) -> usize {
let mut buf: Vec<u8> = vec![]; // The serialized size of a transparent `TxOut` is the serialized size of an amount
self.script_pubkey() // plus the serialized size of the script pubkey.
.write(&mut buf) 8 + self.script_pubkey().serialized_size()
.expect("script does not exceed available memory");
// The length of a transparent TxOut is the length of an amount plus the length of the serialized script pubkey.
8 + buf.len()
} }
} }