hashes: change engine parameter to be mutable reference
What changed, and why it matters
This is a routine internal API cleanup in the rust-bitcoin hashing library. A helper function that feeds data into a hash calculator is changed so callers pass in the calculator by mutable reference instead of handing it over and getting it back. No security vulnerability is present in the diff; it is a usability and ownership-style refactor.
No security action required. Treat as a normal API refactor; verify downstream consumers compile against the new signature if the function is public.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors hashes::encode_to_engine from fn<T,H>(object: &T, mut engine: H) -> H to fn<T,H>(object: &T, engine: &mut H). Callers now pass &mut enc and no longer reassign the returned engine. This removes unnecessary moves/ownership transfer and aligns with idiomatic Rust borrowing. All call sites in sighash.rs, block.rs, and hashes/src/lib.rs are updated consistently. There is no change to hashing semantics, serialization, or finalization behavior.
Changed components
hashes/src/lib.rsbitcoin/src/crypto/sighash.rsprimitives/src/block.rsInspect captured patch +13 / −17
diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs
index 0d7a75f9..709ac712 100644
--- a/bitcoin/src/crypto/sighash.rs
+++ b/bitcoin/src/crypto/sighash.rs
@@ -224,7 +224,7 @@ impl<'s> ScriptPath<'s> {
enc.write_all(&[self.leaf_version.to_consensus()])
.expect("writing to hash engine should never fail");
- enc = hashes::encode_to_engine(self.script, enc);
+ hashes::encode_to_engine(self.script, &mut enc);
let inner = sha256t::Hash::<TapLeafTag>::from_engine(enc);
TapLeafHash::from_byte_array(inner.to_byte_array())
@@ -412,7 +412,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
outputs_length: self.tx.borrow().outputs.len(),
}))
.map_err(SigningDataError::Sighash)?;
- enc = hashes::encode_to_engine(txout, enc);
+ hashes::encode_to_engine(txout, &mut enc);
let hash = sha256::Hash::from_engine(enc);
writer.write_all(&hash.to_byte_array())?;
}
@@ -552,8 +552,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
&& input_index < self.tx.borrow().outputs.len()
{
let mut single_enc = LegacySighash::engine();
- single_enc =
- hashes::encode_to_engine(&self.tx.borrow().outputs[input_index], single_enc);
+ hashes::encode_to_engine(&self.tx.borrow().outputs[input_index], &mut single_enc);
let hash = LegacySighash::from_engine(single_enc);
writer.write_all(hash.as_byte_array())?;
} else {
@@ -790,8 +789,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
let mut enc_prevouts = sha256::Hash::engine();
let mut enc_sequences = sha256::Hash::engine();
for txin in tx.inputs.iter() {
- enc_prevouts = hashes::encode_to_engine(&txin.previous_output, enc_prevouts);
- enc_sequences = hashes::encode_to_engine(&txin.sequence, enc_sequences);
+ hashes::encode_to_engine(&txin.previous_output, &mut enc_prevouts);
+ hashes::encode_to_engine(&txin.sequence, &mut enc_sequences);
}
CommonCache {
prevouts: sha256::Hash::from_engine(enc_prevouts),
@@ -825,10 +824,10 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
let mut enc_amounts = sha256::Hash::engine();
let mut enc_script_pubkeys = sha256::Hash::engine();
for prevout in prevouts {
- enc_amounts = hashes::encode_to_engine(&prevout.borrow().amount, enc_amounts);
- enc_script_pubkeys = hashes::encode_to_engine(
+ hashes::encode_to_engine(&prevout.borrow().amount, &mut enc_amounts);
+ hashes::encode_to_engine(
&(*prevout.borrow().script_pubkey),
- enc_script_pubkeys,
+ &mut enc_script_pubkeys,
);
}
TaprootCache {
diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs
index cc23231b..14fc4117 100644
--- a/hashes/src/lib.rs
+++ b/hashes/src/lib.rs
@@ -199,10 +199,7 @@ pub trait HashEngine: Clone {
}
/// Encodes an object into a hash engine.
-///
-/// Consumes and returns the hash engine to make it easier to call [`HashEngine::finalize`] directly
-/// on the result.
-pub fn encode_to_engine<T, H>(object: &T, mut engine: H) -> H
+pub fn encode_to_engine<T, H>(object: &T, engine: &mut H)
where
T: encoding::Encodable + ?Sized,
H: HashEngine,
@@ -214,7 +211,6 @@ where
break;
}
}
- engine
}
/// Trait which applies to hashes of all types.
diff --git a/primitives/src/block.rs b/primitives/src/block.rs
index 2fcc4c38..8c91f0b2 100644
--- a/primitives/src/block.rs
+++ b/primitives/src/block.rs
@@ -175,7 +175,7 @@ impl Block<Unchecked> {
) -> Option<(WitnessMerkleNode, WitnessCommitment)> {
compute_witness_root(&self.transactions).map(|witness_root| {
let mut encoder = sha256d::Hash::engine();
- encoder = hashes::encode_to_engine(&witness_root, encoder);
+ hashes::encode_to_engine(&witness_root, &mut encoder);
encoder.input(witness_reserved_value);
let witness_commitment = WitnessCommitment::from_byte_array(
sha256d::Hash::from_engine(encoder).to_byte_array(),
@@ -475,8 +475,9 @@ impl Header {
/// Returns the block hash.
// This is the same as `Encodable` but done manually because `Encodable` isn't in `primitives`.
pub fn block_hash(&self) -> BlockHash {
- let bare_hash = hashes::encode_to_engine(self, sha256d::Hash::engine()).finalize();
- BlockHash::from_byte_array(bare_hash.to_byte_array())
+ let mut engine = sha256d::Hash::engine();
+ hashes::encode_to_engine(self, &mut engine);
+ BlockHash::from_byte_array(engine.finalize().to_byte_array())
}
}
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.