Skip to content

Improve zcash_serialized_size() performance #10347

@arya2

Description

@arya2

Motivation

This method is needlessly slow, Zebra now avoids reading large blocks from disk to respond to RPC methods, but every time it writes a block to the chain state, it counts the number of bytes used to represent its serialized encoding.

It's not a significant computation, but it does this sequentially, and it's easy to fix.

Design

Block::zcash_serialized_size
fn zcash_serialized_size(&self) -> usize {
    self.header.zcash_serialized_size() + self.transactions.zcash_serialized_size()
}
Header::zcash_serialized_size
fn zcash_serialized_size(&self) -> usize {
    /// Size of a serialized zcash block header except for the equihash solution
    const HEADER_SIZE: usize = 140;

    let solution_size = match self.solution {
        equihash::Solution::Common(_) => equihash::SOLUTION_SIZE,
        equihash::Solution::Regtest(_) => equihash::REGTEST_SOLUTION_SIZE,
    };

    solution_size + HEADER_SIZE
}
Vec::T::zcash_serialized_size
fn zcash_serialized_size(&self) -> usize {
    let len_size = CompactSizeMessage::try_from(self.len())
        .expect("len fits in MAX_PROTOCOL_MESSAGE_LEN")
        .zcash_serialized_size();

    self.iter()
        .fold(len_size, |acc, t| acc + t.zcash_serialized_size())
}

The serialized size of a transaction can also likely be determined without fully counting every byte in its encoded representation (or perhaps without counting any bytes, if all of the encoded sizes can be determined based on len fields).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions