From 2348449d2a39db6212eff16861c4bff58c015ede Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 10 Sep 2023 01:04:34 +0000 Subject: [PATCH] Stop relying on `std::io::Write`'s `&mut Write` blanket impl `std::io::Write` is implemented for all `&mut std::io::Write`. This makes it easy to have APIs that mix and match owned `Write`s with mutable references to `Write`s. However, in the next commit we add our own `Write` trait which we intend to implement for all `std::io::Write`. Sadly, this is mutually exclusive with a blanket implementation on our own `&mut Write`, as that would conflict with an `std::io::Write` blanket impl. Thus, in order to use the `Write for all &mut Write` blanket impl in rust-bitcoin, we'd have to bound all `Write`s by `std::io::Write`, as we're unable to provide a blanket `Write for &mut Write` impl. Here we stop relying on that blanket impl in order to introduce the new trait in the next commit. --- bitcoin/src/bip158.rs | 2 +- bitcoin/src/consensus/encode.rs | 6 +-- bitcoin/src/crypto/key.rs | 2 +- bitcoin/src/crypto/sighash.rs | 76 ++++++++++++++++----------------- bitcoin/src/taproot.rs | 6 +-- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs index 2028070d..61b3c6e2 100644 --- a/bitcoin/src/bip158.rs +++ b/bitcoin/src/bip158.rs @@ -393,7 +393,7 @@ impl<'a, W: io::Write> GcsFilterWriter<'a, W> { mapped.sort_unstable(); // write number of elements as varint - let mut wrote = VarInt::from(mapped.len()).consensus_encode(&mut self.writer)?; + let mut wrote = VarInt::from(mapped.len()).consensus_encode(self.writer)?; // write out deltas of sorted values into a Golonb-Rice coded bit stream let mut writer = BitStreamWriter::new(self.writer); diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs index b6ed05b5..42d11a1e 100644 --- a/bitcoin/src/consensus/encode.rs +++ b/bitcoin/src/consensus/encode.rs @@ -643,11 +643,11 @@ impl_vec!((u32, Address)); #[cfg(feature = "std")] impl_vec!(AddrV2Message); -pub(crate) fn consensus_encode_with_size( +pub(crate) fn consensus_encode_with_size( data: &[u8], - mut w: W, + w: &mut W, ) -> Result { - let vi_len = VarInt(data.len() as u64).consensus_encode(&mut w)?; + let vi_len = VarInt(data.len() as u64).consensus_encode(w)?; w.emit_slice(data)?; Ok(vi_len + data.len()) } diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index 2805f4e3..366369a4 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -68,7 +68,7 @@ impl PublicKey { } /// Write the public key into a writer - pub fn write_into(&self, mut writer: W) -> Result<(), io::Error> { + pub fn write_into(&self, writer: &mut W) -> Result<(), io::Error> { self.with_serialized(|bytes| writer.write_all(bytes)) } diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index 2b5cd835..859aa34d 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -675,7 +675,7 @@ impl> SighashCache { /// [`io::Write`] trait. pub fn taproot_encode_signing_data_to>( &mut self, - mut writer: Write, + writer: &mut Write, input_index: usize, prevouts: &Prevouts, annex: Option, @@ -687,18 +687,18 @@ impl> SighashCache { let (sighash, anyone_can_pay) = sighash_type.split_anyonecanpay_flag(); // epoch - 0u8.consensus_encode(&mut writer)?; + 0u8.consensus_encode(writer)?; // * Control: // hash_type (1). - (sighash_type as u8).consensus_encode(&mut writer)?; + (sighash_type as u8).consensus_encode(writer)?; // * Transaction Data: // nVersion (4): the nVersion of the transaction. - self.tx.borrow().version.consensus_encode(&mut writer)?; + self.tx.borrow().version.consensus_encode(writer)?; // nLockTime (4): the nLockTime of the transaction. - self.tx.borrow().lock_time.consensus_encode(&mut writer)?; + self.tx.borrow().lock_time.consensus_encode(writer)?; // If the hash_type & 0x80 does not equal SIGHASH_ANYONECANPAY: // sha_prevouts (32): the SHA256 of the serialization of all input outpoints. @@ -706,16 +706,16 @@ impl> SighashCache { // sha_scriptpubkeys (32): the SHA256 of the serialization of all spent output scriptPubKeys. // sha_sequences (32): the SHA256 of the serialization of all input nSequence. if !anyone_can_pay { - self.common_cache().prevouts.consensus_encode(&mut writer)?; - self.taproot_cache(prevouts.get_all()?).amounts.consensus_encode(&mut writer)?; - self.taproot_cache(prevouts.get_all()?).script_pubkeys.consensus_encode(&mut writer)?; - self.common_cache().sequences.consensus_encode(&mut writer)?; + self.common_cache().prevouts.consensus_encode(writer)?; + self.taproot_cache(prevouts.get_all()?).amounts.consensus_encode(writer)?; + self.taproot_cache(prevouts.get_all()?).script_pubkeys.consensus_encode(writer)?; + self.common_cache().sequences.consensus_encode(writer)?; } // If hash_type & 3 does not equal SIGHASH_NONE or SIGHASH_SINGLE: // sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. if sighash != TapSighashType::None && sighash != TapSighashType::Single { - self.common_cache().outputs.consensus_encode(&mut writer)?; + self.common_cache().outputs.consensus_encode(writer)?; } // * Data about this input: @@ -728,7 +728,7 @@ impl> SighashCache { if leaf_hash_code_separator.is_some() { spend_type |= 2u8; } - spend_type.consensus_encode(&mut writer)?; + spend_type.consensus_encode(writer)?; // If hash_type & 0x80 equals SIGHASH_ANYONECANPAY: // outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). @@ -742,12 +742,12 @@ impl> SighashCache { inputs_size: self.tx.borrow().input.len(), })?; let previous_output = prevouts.get(input_index)?; - txin.previous_output.consensus_encode(&mut writer)?; - previous_output.value.consensus_encode(&mut writer)?; - previous_output.script_pubkey.consensus_encode(&mut writer)?; - txin.sequence.consensus_encode(&mut writer)?; + txin.previous_output.consensus_encode(writer)?; + previous_output.value.consensus_encode(writer)?; + previous_output.script_pubkey.consensus_encode(writer)?; + txin.sequence.consensus_encode(writer)?; } else { - (input_index as u32).consensus_encode(&mut writer)?; + (input_index as u32).consensus_encode(writer)?; } // If an annex is present (the lowest bit of spend_type is set): @@ -757,7 +757,7 @@ impl> SighashCache { let mut enc = sha256::Hash::engine(); annex.consensus_encode(&mut enc)?; let hash = sha256::Hash::from_engine(enc); - hash.consensus_encode(&mut writer)?; + hash.consensus_encode(writer)?; } // * Data about this output: @@ -775,7 +775,7 @@ impl> SighashCache { })? .consensus_encode(&mut enc)?; let hash = sha256::Hash::from_engine(enc); - hash.consensus_encode(&mut writer)?; + hash.consensus_encode(writer)?; } // if (scriptpath): @@ -783,9 +783,9 @@ impl> SighashCache { // ss += bytes([0]) // ss += struct.pack("> SighashCache { /// [`Self::p2wpkh_signature_hash`] and [`SighashCache::p2wsh_signature_hash`].) pub fn segwit_v0_encode_signing_data_to( &mut self, - mut writer: Write, + writer: &mut Write, input_index: usize, script_code: &Script, value: Amount, @@ -872,21 +872,21 @@ impl> SighashCache { let (sighash, anyone_can_pay) = sighash_type.split_anyonecanpay_flag(); - self.tx.borrow().version.consensus_encode(&mut writer)?; + self.tx.borrow().version.consensus_encode(writer)?; if !anyone_can_pay { - self.segwit_cache().prevouts.consensus_encode(&mut writer)?; + self.segwit_cache().prevouts.consensus_encode(writer)?; } else { - zero_hash.consensus_encode(&mut writer)?; + zero_hash.consensus_encode(writer)?; } if !anyone_can_pay && sighash != EcdsaSighashType::Single && sighash != EcdsaSighashType::None { - self.segwit_cache().sequences.consensus_encode(&mut writer)?; + self.segwit_cache().sequences.consensus_encode(writer)?; } else { - zero_hash.consensus_encode(&mut writer)?; + zero_hash.consensus_encode(writer)?; } { @@ -896,14 +896,14 @@ impl> SighashCache { inputs_size: self.tx.borrow().input.len(), })?; - txin.previous_output.consensus_encode(&mut writer)?; - script_code.consensus_encode(&mut writer)?; - value.consensus_encode(&mut writer)?; - txin.sequence.consensus_encode(&mut writer)?; + txin.previous_output.consensus_encode(writer)?; + script_code.consensus_encode(writer)?; + value.consensus_encode(writer)?; + txin.sequence.consensus_encode(writer)?; } if sighash != EcdsaSighashType::Single && sighash != EcdsaSighashType::None { - self.segwit_cache().outputs.consensus_encode(&mut writer)?; + self.segwit_cache().outputs.consensus_encode(writer)?; } else if sighash == EcdsaSighashType::Single && input_index < self.tx.borrow().output.len() { let mut single_enc = LegacySighash::engine(); @@ -914,8 +914,8 @@ impl> SighashCache { writer.write_all(&zero_hash[..])?; } - self.tx.borrow().lock_time.consensus_encode(&mut writer)?; - sighash_type.to_u32().consensus_encode(&mut writer)?; + self.tx.borrow().lock_time.consensus_encode(writer)?; + sighash_type.to_u32().consensus_encode(writer)?; Ok(()) } @@ -986,7 +986,7 @@ impl> SighashCache { /// that must be handled by the caller (see [`EncodeSigningDataResult::is_sighash_single_bug`]). pub fn legacy_encode_signing_data_to>( &self, - writer: Write, + writer: &mut Write, input_index: usize, script_pubkey: &Script, sighash_type: U, @@ -1013,7 +1013,7 @@ impl> SighashCache { fn encode_signing_data_to_inner( self_: &Transaction, - mut writer: Write, + writer: &mut Write, input_index: usize, script_pubkey: &Script, sighash_type: u32, @@ -1074,8 +1074,8 @@ impl> SighashCache { _ => unreachable!(), }; // hash the result - tx.consensus_encode(&mut writer)?; - sighash_type.to_le_bytes().consensus_encode(&mut writer)?; + tx.consensus_encode(writer)?; + sighash_type.to_le_bytes().consensus_encode(writer)?; Ok(()) } diff --git a/bitcoin/src/taproot.rs b/bitcoin/src/taproot.rs index 6be5e586..addf3de0 100644 --- a/bitcoin/src/taproot.rs +++ b/bitcoin/src/taproot.rs @@ -1109,7 +1109,7 @@ impl TaprootMerkleBranch { /// # Returns /// /// The number of bytes written to the writer. - pub fn encode(&self, mut writer: Write) -> io::Result { + pub fn encode(&self, writer: &mut Write) -> io::Result { for hash in self.0.iter() { writer.write_all(hash.as_ref())?; } @@ -1237,12 +1237,12 @@ impl ControlBlock { /// # Returns /// /// The number of bytes written to the writer. - pub fn encode(&self, mut writer: Write) -> io::Result { + pub fn encode(&self, writer: &mut Write) -> io::Result { let first_byte: u8 = i32::from(self.output_key_parity) as u8 | self.leaf_version.to_consensus(); writer.write_all(&[first_byte])?; writer.write_all(&self.internal_key.serialize())?; - self.merkle_branch.encode(&mut writer)?; + self.merkle_branch.encode(writer)?; Ok(self.size()) }