Eliminate a heap allocation from PartialMerkleTree encoding & decoding

Just came across this and felt like doing this.
This commit is contained in:
Steven Roose 2023-08-11 20:41:17 +01:00
parent caf53d755d
commit fa10668a35
No known key found for this signature in database
GPG Key ID: 2F2A88D7F8D68E87
1 changed files with 23 additions and 11 deletions

View File

@ -432,26 +432,38 @@ impl PartialMerkleTree {
impl Encodable for PartialMerkleTree { impl Encodable for PartialMerkleTree {
fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> { fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
let ret = self.num_transactions.consensus_encode(w)? + self.hashes.consensus_encode(w)?; let mut ret = self.num_transactions.consensus_encode(w)?;
let mut bytes: Vec<u8> = vec![0; (self.bits.len() + 7) / 8]; ret += self.hashes.consensus_encode(w)?;
for p in 0..self.bits.len() {
bytes[p / 8] |= (self.bits[p] as u8) << (p % 8) as u8; let nb_bytes_for_bits = (self.bits.len() + 7) / 8;
ret += encode::VarInt(nb_bytes_for_bits as u64).consensus_encode(w)?;
for chunk in self.bits.chunks(8) {
let mut byte = 0u8;
for (i, bit) in chunk.iter().enumerate() {
byte |= (*bit as u8) << i;
}
ret += byte.consensus_encode(w)?;
} }
Ok(ret + bytes.consensus_encode(w)?) Ok(ret)
} }
} }
impl Decodable for PartialMerkleTree { impl Decodable for PartialMerkleTree {
fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> { fn consensus_decode_from_finite_reader<R: io::Read + ?Sized>(
r: &mut R,
) -> Result<Self, encode::Error> {
let num_transactions: u32 = Decodable::consensus_decode(r)?; let num_transactions: u32 = Decodable::consensus_decode(r)?;
let hashes: Vec<TxMerkleNode> = Decodable::consensus_decode(r)?; let hashes: Vec<TxMerkleNode> = Decodable::consensus_decode(r)?;
let bytes: Vec<u8> = Decodable::consensus_decode(r)?; let nb_bytes_for_bits = encode::VarInt::consensus_decode(r)?.0 as usize;
let mut bits: Vec<bool> = vec![false; bytes.len() * 8]; let mut bits = vec![false; nb_bytes_for_bits * 8];
for chunk in bits.chunks_mut(8) {
for (p, bit) in bits.iter_mut().enumerate() { let byte = u8::consensus_decode(r)?;
*bit = (bytes[p / 8] & (1 << (p % 8) as u8)) != 0; for (i, bit) in chunk.iter_mut().enumerate() {
*bit = (byte & (1 << i)) != 0;
}
} }
Ok(PartialMerkleTree { num_transactions, hashes, bits }) Ok(PartialMerkleTree { num_transactions, hashes, bits })
} }
} }