Merge rust-bitcoin/rust-bitcoin#1991: Eliminate a heap allocation from PartialMerkleTree encoding & decoding

fa10668a35 Eliminate a heap allocation from PartialMerkleTree encoding & decoding (Steven Roose)

Pull request description:

  Just came across this and felt like doing this.

ACKs for top commit:
  apoelstra:
    ACK fa10668a35
  tcharding:
    ACK fa10668a35

Tree-SHA512: 7167c63077851c4c461b33292948d9b09fe21eb45d52ed278ecf884ce15bc8b21c14040fa1eb5f50bfe51c5cde10abc133d0c59be502de139408c0d107ffa7eb
This commit is contained in:
Andrew Poelstra 2023-08-11 22:09:11 +00:00
commit 19bb55f77e
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
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 })
} }
} }