Skip to content

Commit 56d4bca

Browse files
committed
Merge rust-bitcoin#5417: optimize(block): avoid cloning when encoding unchecked blocks
f26ddba Use as_parts to encode Block<Unchecked> without cloning (Alkamal01) Pull request description: Removes an unnecessary clone in `Block<Unchecked>` encoding. Based on review feedback, this adds `as_parts` to `Block<Unchecked>` instead of introducing new getters. That lets us encode without cloning while keeping the API stable for the 1.0 release. ACKs for top commit: tcharding: ACK f26ddba apoelstra: ACK f26ddba; successfully ran local tests Tree-SHA512: 224dbb6dd8e87ade12c0c2e70257d04710d09a06fae028118beef53ffd88d98b6ab8d70d6cad484514f07043c9072320b49fd23605b1769cbece76566a8ab7ee
2 parents 4cfcd8c + f26ddba commit 56d4bca

4 files changed

Lines changed: 14 additions & 4 deletions

File tree

api/primitives/all-features.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,6 +1465,7 @@ pub fn bitcoin_primitives::block::Block<V>::fmt(&self, f: &mut core::fmt::Format
14651465
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Checked>::cached_witness_root(&self) -> core::option::Option<bitcoin_primitives::WitnessMerkleNode>
14661466
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Checked>::header(&self) -> &bitcoin_primitives::block::Header
14671467
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Checked>::transactions(&self) -> &[bitcoin_primitives::transaction::Transaction]
1468+
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Unchecked>::as_parts(&self) -> (&bitcoin_primitives::block::Header, &[bitcoin_primitives::transaction::Transaction])
14681469
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Unchecked>::assume_checked(self, witness_root: core::option::Option<bitcoin_primitives::WitnessMerkleNode>) -> bitcoin_primitives::block::Block<bitcoin_primitives::block::Checked>
14691470
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Unchecked>::check_merkle_root(&self) -> bool
14701471
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Unchecked>::check_witness_commitment(&self) -> (bool, core::option::Option<bitcoin_primitives::WitnessMerkleNode>)

api/primitives/alloc-only.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,7 @@ pub fn bitcoin_primitives::block::Block<V>::fmt(&self, f: &mut core::fmt::Format
12761276
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Checked>::cached_witness_root(&self) -> core::option::Option<bitcoin_primitives::WitnessMerkleNode>
12771277
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Checked>::header(&self) -> &bitcoin_primitives::block::Header
12781278
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Checked>::transactions(&self) -> &[bitcoin_primitives::transaction::Transaction]
1279+
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Unchecked>::as_parts(&self) -> (&bitcoin_primitives::block::Header, &[bitcoin_primitives::transaction::Transaction])
12791280
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Unchecked>::assume_checked(self, witness_root: core::option::Option<bitcoin_primitives::WitnessMerkleNode>) -> bitcoin_primitives::block::Block<bitcoin_primitives::block::Checked>
12801281
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Unchecked>::check_merkle_root(&self) -> bool
12811282
pub fn bitcoin_primitives::block::Block<bitcoin_primitives::block::Unchecked>::check_witness_commitment(&self) -> (bool, core::option::Option<bitcoin_primitives::WitnessMerkleNode>)

bitcoin/src/blockdata/block.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,14 @@ fn block_base_size(transactions: &[Transaction]) -> usize {
236236
impl Encodable for Block<Unchecked> {
237237
#[inline]
238238
fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
239-
// TODO: Should we be able to encode without cloning?
240-
// This is ok, we decode as unchecked anyway.
241-
let block = self.clone().assume_checked(None);
242-
block.consensus_encode(w)
239+
let (header, transactions) = self.as_parts();
240+
let mut len = 0;
241+
len += header.consensus_encode(w)?;
242+
len += w.emit_compact_size(transactions.len())?;
243+
for tx in transactions.iter() {
244+
len += tx.consensus_encode(w)?;
245+
}
246+
Ok(len)
243247
}
244248
}
245249

primitives/src/block.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ impl Block<Unchecked> {
113113
#[inline]
114114
pub fn into_parts(self) -> (Header, Vec<Transaction>) { (self.header, self.transactions) }
115115

116+
/// Returns the constituent parts of the block by reference.
117+
#[inline]
118+
pub fn as_parts(&self) -> (&Header, &[Transaction]) { (&self.header, &self.transactions) }
119+
116120
/// Validates (or checks) a block.
117121
///
118122
/// We define valid as:

0 commit comments

Comments
 (0)