Repository: rust-bitcoin/rust-bitcoin
Pull request #1342 (2022-10-25 09:03:45)

Re-export base64 when enabled
`base64` used to be exported until commit 23ee0930c75c3c028572c521e0906fd4f95b6b92 which removed the `pub extern crate` declaration.


Patch:
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index 2a64cb30..28c56abf 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -658,7 +658,7 @@ pub fn encode_signing_data_to<Write: io::Write, U: Into<u32>>(
         script_pubkey: &Script,
         sighash_type: U,
     ) -> EncodeSigningDataResult<io::Error> {
-        use crate::sighash::{self, SighashCache};
+        use crate::util::sighash::{self, SighashCache};
         use EncodeSigningDataResult::*;
 
         assert!(input_index < self.input.len());  // Panic on OOB
@@ -708,7 +708,7 @@ pub fn signature_hash(
     ) -> Sighash {
         assert!(input_index < self.input.len());  // Panic on OOB, enables expect below.
 
-        let cache = crate::sighash::SighashCache::new(self);
+        let cache = crate::util::sighash::SighashCache::new(self);
         cache.legacy_signature_hash(input_index, script_pubkey, sighash_u32)
             .expect("cache method doesn't error")
     }
diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs
index 179fa541..6f2ff7f5 100644
--- a/bitcoin/src/blockdata/witness.rs
+++ b/bitcoin/src/blockdata/witness.rs
@@ -9,7 +9,7 @@
 
 use crate::consensus::encode::{Error, MAX_VEC_SIZE};
 use crate::consensus::{Decodable, Encodable, WriteExt};
-use crate::sighash::EcdsaSighashType;
+use crate::util::sighash::EcdsaSighashType;
 use crate::io::{self, Read, Write};
 use crate::prelude::*;
 use crate::VarInt;
diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs
index 72d01764..20c2a46b 100644
--- a/bitcoin/src/lib.rs
+++ b/bitcoin/src/lib.rs
@@ -65,6 +65,11 @@
 pub use bitcoinconsensus;
 pub use {bech32, bitcoin_hashes as hashes, secp256k1};
 
+// Re-export base64 when enabled
+#[cfg(feature = "base64")]
+#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
+pub use base64;
+
 #[cfg(feature = "serde")]
 #[macro_use]
 extern crate actual_serde as serde;
@@ -89,7 +94,6 @@
 pub mod hash_types;
 pub mod policy;
 pub mod pow;
-pub mod sighash;
 pub mod sign_message;
 pub mod util;
 
@@ -115,7 +119,7 @@
 pub use crate::util::key::{KeyPair, PrivateKey, PublicKey, XOnlyPublicKey};
 pub use crate::util::merkleblock::MerkleBlock;
 pub use crate::util::schnorr::{self, SchnorrSig, SchnorrSigError};
-pub use crate::util::{psbt, Error};
+pub use crate::util::{psbt, sighash, Error};
 
 #[cfg(not(feature = "std"))]
 mod io_extras {
diff --git a/bitcoin/src/util/ecdsa.rs b/bitcoin/src/util/ecdsa.rs
index 30835a3f..682ab298 100644
--- a/bitcoin/src/util/ecdsa.rs
+++ b/bitcoin/src/util/ecdsa.rs
@@ -13,7 +13,7 @@
 
 use crate::prelude::*;
 use crate::hashes::hex::{self, FromHex};
-use crate::sighash::{EcdsaSighashType, NonStandardSighashType};
+use crate::util::sighash::{EcdsaSighashType, NonStandardSighashType};
 
 /// An ECDSA signature with the corresponding hash type.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
diff --git a/bitcoin/src/util/mod.rs b/bitcoin/src/util/mod.rs
index e254a6c3..a34b8212 100644
--- a/bitcoin/src/util/mod.rs
+++ b/bitcoin/src/util/mod.rs
@@ -15,6 +15,7 @@
 pub mod merkleblock;
 pub mod psbt;
 pub mod taproot;
+pub mod sighash;
 
 pub(crate) mod endian;
 
diff --git a/bitcoin/src/util/psbt/error.rs b/bitcoin/src/util/psbt/error.rs
index c2ca9b60..4424a809 100644
--- a/bitcoin/src/util/psbt/error.rs
+++ b/bitcoin/src/util/psbt/error.rs
@@ -74,10 +74,6 @@ pub enum Error {
     CombineInconsistentKeySources(Box<ExtendedPubKey>),
     /// Serialization error in bitcoin consensus-encoded structures
     ConsensusEncoding,
-    /// Negative fee
-    NegativeFee,
-    /// Integer overflow in fee calculation
-    FeeOverflow,
 }
 
 impl fmt::Display for Error {
@@ -105,9 +101,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             },
             Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) },
             Error::ConsensusEncoding => f.write_str("bitcoin consensus or BIP-174 encoding error"),
-            Error::NegativeFee => f.write_str("PSBT has a negative fee which is not allowed"),
-            Error::FeeOverflow => f.write_str("integer overflow in fee calculation"),
-
         }
     }
 }
@@ -135,9 +128,7 @@ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
             | NonStandardSighashType(_)
             | InvalidPreimageHashPair{ .. }
             | CombineInconsistentKeySources(_)
-            | ConsensusEncoding
-            | NegativeFee
-            | FeeOverflow => None,
+            | ConsensusEncoding => None,
         }
     }
 }
diff --git a/bitcoin/src/util/psbt/map/input.rs b/bitcoin/src/util/psbt/map/input.rs
index 5314ea0d..1e9186f6 100644
--- a/bitcoin/src/util/psbt/map/input.rs
+++ b/bitcoin/src/util/psbt/map/input.rs
@@ -21,9 +21,10 @@
 use crate::util::psbt::serialize::Deserialize;
 use crate::util::psbt::{Error, error};
 use crate::util::key::PublicKey;
-use crate::sighash::{NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, SchnorrSighashType};
+use crate::util::sighash::{NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, SchnorrSighashType};
 use crate::util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
-use crate::{sighash, EcdsaSig, SchnorrSig};
+use crate::util::sighash;
+use crate::{EcdsaSig, SchnorrSig};
 
 /// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
 const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
diff --git a/bitcoin/src/util/psbt/mod.rs b/bitcoin/src/util/psbt/mod.rs
index b103968f..1ee5d218 100644
--- a/bitcoin/src/util/psbt/mod.rs
+++ b/bitcoin/src/util/psbt/mod.rs
@@ -16,7 +16,7 @@
 use secp256k1::{Message, Secp256k1, Signing};
 use bitcoin_internals::write_err;
 
-use crate::{prelude::*, Amount};
+use crate::prelude::*;
 use crate::io;
 
 use crate::blockdata::script::Script;
@@ -25,9 +25,9 @@
 use crate::util::bip32::{self, ExtendedPrivKey, ExtendedPubKey, KeySource};
 use crate::util::ecdsa::{EcdsaSig, EcdsaSigError};
 use crate::util::key::{PublicKey, PrivateKey};
-use crate::sighash::{self, EcdsaSighashType, SighashCache};
+use crate::util::sighash::{self, EcdsaSighashType, SighashCache};
 
-pub use crate::sighash::Prevouts;
+pub use crate::util::sighash::Prevouts;
 
 #[macro_use]
 mod macros;
@@ -437,28 +437,6 @@ fn output_type(&self, input_index: usize) -> Result<OutputType, SignError> {
         // because there has been a new softfork that we do not yet support.
         Err(SignError::UnknownOutputType)
     }
-
-    /// Calculates transaction fee.
-    ///
-    /// 'Fee' being the amount that will be paid for mining a transaction with the current inputs
-    /// and outputs i.e., the difference in value of the total inputs and the total outputs.
-    ///
-    /// ## Errors
-    ///
-    /// - [`Error::MissingUtxo`] when UTXO information for any input is not present or is invalid.
-    /// - [`Error::NegativeFee`] if calculated value is negative.
-    /// - [`Error::FeeOverflow`] if an integer overflow occurs.
-    pub fn fee(&self) -> Result<Amount, Error> {
-        let mut inputs: u64 = 0;
-        for utxo in self.iter_funding_utxos() {
-            inputs = inputs.checked_add(utxo?.value).ok_or(Error::FeeOverflow)?;
-        }
-        let mut outputs: u64 = 0;
-        for out in &self.unsigned_tx.output {
-            outputs = outputs.checked_add(out.value).ok_or(Error::FeeOverflow)?;
-        }
-        inputs.checked_sub(outputs).map(Amount::from_sat).ok_or(Error::NegativeFee)
-    }
 }
 
 /// Data required to call [`GetKey`] to get the private key to sign an input.
@@ -1152,7 +1130,7 @@ mod bip_vectors {
         use crate::util::psbt::map::{Map, Input, Output};
         use crate::util::psbt::raw;
         use crate::util::psbt::{PartiallySignedTransaction, Error};
-        use crate::sighash::EcdsaSighashType;
+        use crate::util::sighash::EcdsaSighashType;
         use std::collections::BTreeMap;
         use crate::blockdata::witness::Witness;
         use crate::internal_macros::hex_script;
@@ -1711,106 +1689,6 @@ fn get_key_btree_map() {
         assert_eq!(got.unwrap(), priv_key)
     }
 
-    #[test]
-    fn test_fee() {
-        let output_0_val = 99999699;
-        let output_1_val = 100000000;
-        let prev_output_val = 200000000;
-
-        let mut t = PartiallySignedTransaction {
-            unsigned_tx: Transaction {
-                version: 2,
-                lock_time: absolute::PackedLockTime(1257139),
-                input: vec![TxIn {
-                    previous_output: OutPoint {
-                        txid: Txid::from_hex(
-                            "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
-                        ).unwrap(),
-                        vout: 0,
-                    },
-                    sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
-                    ..Default::default()
-                }],
-                output: vec![
-                    TxOut {
-                        value: output_0_val,
-                        ..Default::default()
-                    },
-                    TxOut {
-                        value: output_1_val,
-                        ..Default::default()
-                    },
-                ],
-            },
-            xpub: Default::default(),
-            version: 0,
-            proprietary: BTreeMap::new(),
-            unknown: BTreeMap::new(),
-
-            inputs: vec![Input {
-                non_witness_utxo: Some(Transaction {
-                    version: 1,
-                    lock_time: absolute::PackedLockTime::ZERO,
-                    input: vec![TxIn {
-                        previous_output: OutPoint {
-                            txid: Txid::from_hex(
-                                "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
-                            ).unwrap(),
-                            vout: 1,
-                        },
-                        sequence: Sequence::MAX,
-                       ..Default::default()
-                    },
-                    TxIn {
-                        previous_output: OutPoint {
-                            txid: Txid::from_hex(
-                                "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
-                            ).unwrap(),
-                            vout: 1,
-                        },
-                        sequence: Sequence::MAX,
-                        ..Default::default()
-                    }],
-                    output: vec![
-                        TxOut {
-                            value: prev_output_val,
-                            ..Default::default()
-                        },
-                        TxOut {
-                            value: 190303501938,
-                            ..Default::default()
-                        },
-                    ],
-                }),
-                ..Default::default()
-            },],
-            outputs: vec![
-                Output {
-                    ..Default::default()
-                },
-                Output {
-                    ..Default::default()
-                },
-            ],
-        };
-        assert_eq!(
-            t.fee().expect("fee calculation"),
-            Amount::from_sat(prev_output_val - (output_0_val + output_1_val))
-        );
-        // no previous output
-        let mut t2 = t.clone();
-        t2.inputs[0].non_witness_utxo = None;
-        assert_eq!(t2.fee(), Err(Error::MissingUtxo));
-        //  negative fee
-        let mut t3 = t.clone();
-        t3.unsigned_tx.output[0].value = prev_output_val;
-        assert_eq!(t3.fee(), Err(Error::NegativeFee));
-        // overflow
-        t.unsigned_tx.output[0].value = u64::max_value();
-        t.unsigned_tx.output[1].value = u64::max_value();
-        assert_eq!(t.fee(), Err(Error::FeeOverflow));
-    }
-
     #[test]
     #[cfg(feature = "rand")]
     fn sign_psbt() {
diff --git a/bitcoin/src/sighash.rs b/bitcoin/src/util/sighash.rs
similarity index 99%
rename from bitcoin/src/sighash.rs
rename to bitcoin/src/util/sighash.rs
index 3b3fe380..cbf31c11 100644
--- a/bitcoin/src/sighash.rs
+++ b/bitcoin/src/util/sighash.rs
@@ -1080,7 +1080,7 @@ mod tests {
     use crate::internal_macros::{hex_into, hex_script, hex_decode, hex_from_slice};
     use crate::network::constants::Network;
     use crate::util::key::PublicKey;
-    use crate::sighash::{Annex, Error, Prevouts, ScriptPath, SighashCache};
+    use crate::util::sighash::{Annex, Error, Prevouts, ScriptPath, SighashCache};
     use crate::util::taproot::{TapTweakHash, TapSighashHash, TapBranchHash, TapLeafHash};
 
     extern crate serde_json;
@@ -1109,7 +1109,7 @@ fn sighash_single_bug() {
     #[cfg(feature = "serde")]
     fn legacy_sighash() {
         use serde_json::Value;
-        use crate::sighash::SighashCache;
+        use crate::util::sighash::SighashCache;
 
         fn run_test_sighash(tx: &str, script: &str, input_index: usize, hash_type: i64, expected_result: &str) {
             let tx: Transaction = deserialize(&Vec::from_hex(tx).unwrap()[..]).unwrap();
@@ -1127,7 +1127,7 @@ fn run_test_sighash(tx: &str, script: &str, input_index: usize, hash_type: i64,
         // These test vectors were stolen from libbtc, which is Copyright 2014 Jonas Schnelli MIT
         // They were transformed by replacing {...} with run_test_sighash(...), then the ones containing
         // OP_CODESEPARATOR in their pubkeys were removed
-        let data = include_str!("../test_data/legacy_sighash.json");
+        let data = include_str!("../../test_data/legacy_sighash.json");
 
         let testdata = serde_json::from_str::<Value>(data).unwrap().as_array().unwrap().clone();
         for t in testdata.iter().skip(1) {
@@ -1479,7 +1479,7 @@ fn bip_341_sighash_tests() {
     }
 
     fn bip_341_read_json() -> serde_json::Value {
-        let json_str = include_str!("../test_data/bip341_tests.json");
+        let json_str = include_str!("../../test_data/bip341_tests.json");
         serde_json::from_str(json_str).expect("JSON was not well-formatted")
     }
 


Test patch:
diff --git a/bitcoin/contrib/test.sh b/bitcoin/contrib/test.sh
index b3446628..69805acc 100755
--- a/bitcoin/contrib/test.sh
+++ b/bitcoin/contrib/test.sh
@@ -20,6 +20,9 @@ fi
 
 # We should not have any duplicate dependencies. This catches mistakes made upgrading dependencies
 # in one crate and not in another (e.g. upgrade bitcoin_hashes in bitcoin but not in secp).
+cargo update -p serde --precise 1.0.142
+cargo update -p serde_test --precise 1.0.142
+cargo update -p serde_derive --precise 1.0.142
 duplicate_dependencies=$(cargo tree  --target=all --all-features --duplicates | wc -l)
 if [ "$duplicate_dependencies" -ne 0 ]; then
     echo "Dependency tree is broken, contains duplicates"
@@ -117,5 +120,8 @@ then
     # Adding an empty workspace section excludes this crate from the rust-bitcoin workspace.
     echo '[workspace]\n\n' >> Cargo.toml
 
+    cargo update -p serde --precise 1.0.142
+    cargo update -p serde_derive --precise 1.0.142
+
     cargo test --verbose
 fi