Repository: rust-bitcoin/rust-bitcoin
Pull request #2188 (2023-11-14 04:19:10)

Bump MSRV to Rust version 1.56.1
Rust version 1.56.0 introduced edition 2021. Shortly afterwards, on October 21 2021 Rust version 1.56.1 was released.

Debian stable is currently shipping `rustc 1.63.0`. Our stated MSRV policy is: In Debian stable and at least 2 years old. Therefore our MSRV policy is met by Rust version 1.56.1 and we can strat to bump our MSRV org wide. Start by bumping the `rust-bitcoin` and `hashes` MSRV to Rust 1.56.1

Start by bumping the `rust-bitcoin` and `hashes` MSRV to Rust 1.56.1, includes:
    
- Update docs.
- Update CI and remove pinning.
- Update the build files and remove now stale cfg attributes rust_v_1_x for values less than the new MSRV.
- Use new `IntoIterator` for arrays so we no longer need to allocate a vector to iterate.


Links:

- https://blog.rust-lang.org/2021/11/01/Rust-1.56.1.html
- https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
- https://packages.debian.org/stable/rust/rustc

tcharding: Implemented suggestions and squashed it all into a single patch, re-wrote git log and PR description to match new patch.
tcharding: Oh, sorry man was working while you reviewed. I added a patch to update to edition 2021.
Kixunil: Oh, I just notice you didn't set `rust-version` in `Cargo.toml`. Was it on purpose?
tcharding: Not on purpose, just an omission on my part. Will add
apoelstra: cc @TheBlueMatt @stevenroose I'll give you two a week to comment or veto this, or else I'll merge it on Wednesday Nov 22.
apoelstra: @TheBlueMatt yep, for sure. We're in no particular rush.
Kixunil: Well it won't be released right now anyway so it shouldn't matter? Or is that user using our `master` branch?
tcharding: Thanks man! Rebased.
apoelstra: Might as well do it now then, since we don't have a major release planned til April.

Patch:
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index a59589ef..9ec28ce0 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -66,7 +66,7 @@ jobs:
         run: ./contrib/test.sh
 
   MSRV:
-    name: Test - 1.48.0 toolchain
+    name: Test - 1.56.1 toolchain
     runs-on: ubuntu-latest
     strategy:
       fail-fast: false
@@ -76,7 +76,7 @@ jobs:
       - name: Checkout Toolchain
         uses: dtolnay/rust-toolchain@stable
         with:
-          toolchain: "1.48.0"
+          toolchain: "1.56.1"
       - name: Running test script
         env:
           DO_FEATURE_MATRIX: true
diff --git a/Cargo.toml b/Cargo.toml
index 42895c92..dda25c25 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,6 @@
 [workspace]
 members = ["bitcoin", "hashes", "internals", "fuzz", "io"]
+resolver = "2"
 
 [patch.crates-io.bitcoin]
 path = "bitcoin"
diff --git a/README.md b/README.md
index 33c869a6..c9d21cef 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
     <a href="https://github.com/rust-bitcoin/rust-bitcoin/blob/master/LICENSE"><img alt="CC0 1.0 Universal Licensed" src="https://img.shields.io/badge/license-CC0--1.0-blue.svg"/></a>
     <a href="https://github.com/rust-bitcoin/rust-bitcoin/actions?query=workflow%3AContinuous%20integration"><img alt="CI Status" src="https://github.com/rust-bitcoin/rust-bitcoin/workflows/Continuous%20integration/badge.svg"></a>
     <a href="https://docs.rs/bitcoin"><img alt="API Docs" src="https://img.shields.io/badge/docs.rs-bitcoin-green"/></a>
-    <a href="https://blog.rust-lang.org/2020/02/27/Rust-1.48.0.html"><img alt="Rustc Version 1.48.0+" src="https://img.shields.io/badge/rustc-1.48.0%2B-lightgrey.svg"/></a>
+    <a href="https://blog.rust-lang.org/2020/02/27/Rust-1.56.1.html"><img alt="Rustc Version 1.56.1+" src="https://img.shields.io/badge/rustc-1.56.1%2B-lightgrey.svg"/></a>
     <a href="https://gnusha.org/bitcoin-rust/"><img alt="Chat on IRC" src="https://img.shields.io/badge/irc-%23bitcoin--rust%20on%20libera.chat-blue"></a>
     <a href="https://github.com/model-checking/kani"><imp alt="kani" src="https://github.com/rust-bitcoin/rust-bitcoin/actions/workflows/kani.yaml/badge.svg"></a>
   </p>
@@ -69,7 +69,7 @@ For more information please see `./CONTRIBUTING.md`.
 
 ## Minimum Supported Rust Version (MSRV)
 
-This library should always compile with any combination of features on **Rust 1.48.0**.
+This library should always compile with any combination of features on **Rust 1.56.1**.
 
 To build with the MSRV you will likely need to pin a bunch of dependencies, see `./contrib/test.sh`
 for the current list.
diff --git a/bitcoin/CHANGELOG.md b/bitcoin/CHANGELOG.md
index ebc8f9fb..b5b1d624 100644
--- a/bitcoin/CHANGELOG.md
+++ b/bitcoin/CHANGELOG.md
@@ -1,3 +1,7 @@
+# unreleased
+
+- Bump MSRV to Rust 1.56.1
+
 # 0.31.1 - 2023-10-18
 
 - Bump MSRV to Rust 1.48.0 [#1729](https://github.com/rust-bitcoin/rust-bitcoin/pull/1729)
diff --git a/bitcoin/Cargo.toml b/bitcoin/Cargo.toml
index aa9f6159..3714b2fe 100644
--- a/bitcoin/Cargo.toml
+++ b/bitcoin/Cargo.toml
@@ -9,7 +9,8 @@ description = "General purpose library for using and interoperating with Bitcoin
 categories = ["cryptography::cryptocurrencies"]
 keywords = [ "crypto", "bitcoin" ]
 readme = "../README.md"
-edition = "2018"
+edition = "2021"
+rust-version = "1.56.1"
 exclude = ["tests", "contrib"]
 
 [features]
diff --git a/bitcoin/build.rs b/bitcoin/build.rs
index b5e2f5f6..15add3f3 100644
--- a/bitcoin/build.rs
+++ b/bitcoin/build.rs
@@ -1,4 +1,4 @@
-const MSRV_MINOR: u64 = 48;
+const MSRV_MINOR: u64 = 56;
 
 fn main() {
     let rustc = std::env::var_os("RUSTC");
diff --git a/bitcoin/embedded/Cargo.toml b/bitcoin/embedded/Cargo.toml
index 9ea41c17..726f3857 100644
--- a/bitcoin/embedded/Cargo.toml
+++ b/bitcoin/embedded/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 authors = ["Riccardo Casatta <riccardo@casatta.it>", "Dev Random <c1.devrandom@niftybox.net>"]
-edition = "2018"
+edition = "2021"
 readme = "README.md"
 name = "embedded"
 version = "0.1.0"
diff --git a/bitcoin/src/base58.rs b/bitcoin/src/base58.rs
index 8f5b0330..a68e8131 100644
--- a/bitcoin/src/base58.rs
+++ b/bitcoin/src/base58.rs
@@ -6,7 +6,6 @@
 //! strings respectively.
 //!
 
-use core::convert::TryInto;
 use core::{fmt, iter, slice, str};
 
 use hashes::{sha256d, Hash};
diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs
index 49347977..34eeb088 100644
--- a/bitcoin/src/bip158.rs
+++ b/bitcoin/src/bip158.rs
@@ -39,7 +39,6 @@
 //!
 
 use core::cmp::{self, Ordering};
-use core::convert::TryInto;
 use core::fmt::{self, Display, Formatter};
 
 use hashes::{siphash24, Hash};
diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs
index 059278a5..06b0cf98 100644
--- a/bitcoin/src/bip32.rs
+++ b/bitcoin/src/bip32.rs
@@ -6,7 +6,6 @@
 //! at <https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki>.
 //!
 
-use core::convert::TryInto;
 use core::default::Default;
 use core::ops::Index;
 use core::str::FromStr;
diff --git a/bitcoin/src/blockdata/locktime/absolute.rs b/bitcoin/src/blockdata/locktime/absolute.rs
index ceb25121..fed21aab 100644
--- a/bitcoin/src/blockdata/locktime/absolute.rs
+++ b/bitcoin/src/blockdata/locktime/absolute.rs
@@ -374,14 +374,12 @@ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("a u32"
             // calls visit_u64, even when called from Deserializer::deserialize_u32. The
             // other visit_u*s have default implementations that forward to visit_u64.
             fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<u32, E> {
-                use core::convert::TryInto;
                 v.try_into().map_err(|_| {
                     E::invalid_value(serde::de::Unexpected::Unsigned(v), &"a 32-bit number")
                 })
             }
             // Also do the signed version, just for good measure.
             fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<u32, E> {
-                use core::convert::TryInto;
                 v.try_into().map_err(|_| {
                     E::invalid_value(serde::de::Unexpected::Signed(v), &"a 32-bit number")
                 })
diff --git a/bitcoin/src/blockdata/locktime/relative.rs b/bitcoin/src/blockdata/locktime/relative.rs
index d8f3bfa4..636b85df 100644
--- a/bitcoin/src/blockdata/locktime/relative.rs
+++ b/bitcoin/src/blockdata/locktime/relative.rs
@@ -6,7 +6,6 @@
 //! whether bit 22 of the `u32` consensus value is set.
 //!
 
-use core::convert::TryFrom;
 use core::fmt;
 
 #[cfg(all(test, mutate))]
diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs
index b9da4c56..117e34d0 100644
--- a/bitcoin/src/blockdata/script/borrowed.rs
+++ b/bitcoin/src/blockdata/script/borrowed.rs
@@ -2,9 +2,9 @@
 
 use core::convert::{TryFrom, TryInto};
 use core::fmt;
-#[cfg(rust_v_1_53)]
-use core::ops::Bound;
-use core::ops::{Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
+use core::ops::{
+    Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
+};
 
 use hashes::Hash;
 use secp256k1::{Secp256k1, Verification};
@@ -653,7 +653,6 @@ fn index(&self, index: $type) -> &Self::Output {
     RangeTo<usize>,
     RangeFull,
     RangeInclusive<usize>,
-    RangeToInclusive<usize>
+    RangeToInclusive<usize>,
+    (Bound<usize>, Bound<usize>)
 );
-#[cfg(rust_v_1_53)]
-delegate_index!((Bound<usize>, Bound<usize>));
diff --git a/bitcoin/src/blockdata/script/instruction.rs b/bitcoin/src/blockdata/script/instruction.rs
index 6c3da7bf..5b941cf8 100644
--- a/bitcoin/src/blockdata/script/instruction.rs
+++ b/bitcoin/src/blockdata/script/instruction.rs
@@ -1,7 +1,5 @@
 // SPDX-License-Identifier: CC0-1.0
 
-use core::convert::TryInto;
-
 use crate::blockdata::opcodes::{self, Opcode};
 use crate::blockdata::script::{read_uint_iter, Error, PushBytes, Script, ScriptBuf, UintError};
 
diff --git a/bitcoin/src/blockdata/script/push_bytes.rs b/bitcoin/src/blockdata/script/push_bytes.rs
index 3baec542..6ca8a906 100644
--- a/bitcoin/src/blockdata/script/push_bytes.rs
+++ b/bitcoin/src/blockdata/script/push_bytes.rs
@@ -16,10 +16,8 @@
 /// break invariants. Therefore auditing this module should be sufficient.
 mod primitive {
     use core::convert::{TryFrom, TryInto};
-    #[cfg(rust_v_1_53)]
-    use core::ops::Bound;
     use core::ops::{
-        Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
+        Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
     };
 
     use super::PushBytesError;
@@ -105,10 +103,9 @@ fn index(&self, index: $type) -> &Self::Output {
         RangeTo<usize>,
         RangeFull,
         RangeInclusive<usize>,
-        RangeToInclusive<usize>
+        RangeToInclusive<usize>,
+        (Bound<usize>, Bound<usize>)
     );
-    #[cfg(rust_v_1_53)]
-    delegate_index!((Bound<usize>, Bound<usize>));
 
     impl Index<usize> for PushBytes {
         type Output = u8;
diff --git a/bitcoin/src/blockdata/script/witness_program.rs b/bitcoin/src/blockdata/script/witness_program.rs
index d030f64c..1b792a51 100644
--- a/bitcoin/src/blockdata/script/witness_program.rs
+++ b/bitcoin/src/blockdata/script/witness_program.rs
@@ -7,7 +7,6 @@
 //!
 //! [BIP141]: <https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki>
 
-use core::convert::TryInto;
 use core::fmt;
 
 use crate::blockdata::script::witness_version::WitnessVersion;
diff --git a/bitcoin/src/blockdata/script/witness_version.rs b/bitcoin/src/blockdata/script/witness_version.rs
index cf933432..6897631f 100644
--- a/bitcoin/src/blockdata/script/witness_version.rs
+++ b/bitcoin/src/blockdata/script/witness_version.rs
@@ -7,7 +7,6 @@
 //!
 //! [BIP141]: <https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki>
 
-use core::convert::TryFrom;
 use core::fmt;
 use core::str::FromStr;
 
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index 68622ef1..405609d6 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -11,7 +11,6 @@
 //! This module provides the structures and functions needed to support transactions.
 //!
 
-use core::convert::TryFrom;
 use core::default::Default;
 use core::{cmp, fmt, str};
 
diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs
index ef72b551..920f7345 100644
--- a/bitcoin/src/blockdata/witness.rs
+++ b/bitcoin/src/blockdata/witness.rs
@@ -5,7 +5,6 @@
 //! This module contains the [`Witness`] struct and related methods to operate on it
 //!
 
-use core::convert::TryInto;
 use core::fmt;
 use core::ops::Index;
 
diff --git a/bitcoin/src/network.rs b/bitcoin/src/network.rs
index c66ab070..32102715 100644
--- a/bitcoin/src/network.rs
+++ b/bitcoin/src/network.rs
@@ -18,7 +18,6 @@
 //! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]);
 //! ```
 
-use core::convert::TryFrom;
 use core::fmt;
 use core::fmt::Display;
 use core::str::FromStr;
diff --git a/bitcoin/src/p2p/message.rs b/bitcoin/src/p2p/message.rs
index 448e8a1c..457957f3 100644
--- a/bitcoin/src/p2p/message.rs
+++ b/bitcoin/src/p2p/message.rs
@@ -6,7 +6,6 @@
 //! are used for (de)serializing Bitcoin objects for transmission on the network.
 //!
 
-use core::convert::TryFrom;
 use core::{fmt, iter};
 
 use hashes::{sha256d, Hash};
diff --git a/bitcoin/src/p2p/mod.rs b/bitcoin/src/p2p/mod.rs
index 3132c025..a8ec758c 100644
--- a/bitcoin/src/p2p/mod.rs
+++ b/bitcoin/src/p2p/mod.rs
@@ -20,7 +20,6 @@
 #[cfg(feature = "std")]
 pub mod message_network;
 
-use core::convert::TryFrom;
 use core::str::FromStr;
 use core::{fmt, ops};
 
diff --git a/bitcoin/src/parse.rs b/bitcoin/src/parse.rs
index aebc5f8d..67b66048 100644
--- a/bitcoin/src/parse.rs
+++ b/bitcoin/src/parse.rs
@@ -1,6 +1,5 @@
 // SPDX-License-Identifier: CC0-1.0
 
-use core::convert::TryFrom;
 use core::fmt;
 use core::str::FromStr;
 
diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs
index cc25654a..bb095b07 100644
--- a/bitcoin/src/pow.rs
+++ b/bitcoin/src/pow.rs
@@ -834,8 +834,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:x}", self.0)
 #[cfg(feature = "serde")]
 impl<'de> crate::serde::Deserialize<'de> for U256 {
     fn deserialize<D: crate::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
-        use core::convert::TryInto;
-
         use hex::FromHex;
 
         use crate::serde::de;
diff --git a/bitcoin/src/psbt/map/global.rs b/bitcoin/src/psbt/map/global.rs
index 22a25f4e..53c33c6e 100644
--- a/bitcoin/src/psbt/map/global.rs
+++ b/bitcoin/src/psbt/map/global.rs
@@ -1,7 +1,5 @@
 // SPDX-License-Identifier: CC0-1.0
 
-use core::convert::TryFrom;
-
 use crate::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpub};
 use crate::blockdata::transaction::Transaction;
 use crate::consensus::encode::MAX_VEC_SIZE;
diff --git a/bitcoin/src/psbt/map/input.rs b/bitcoin/src/psbt/map/input.rs
index f74a4ee5..5deb923d 100644
--- a/bitcoin/src/psbt/map/input.rs
+++ b/bitcoin/src/psbt/map/input.rs
@@ -1,6 +1,5 @@
 // SPDX-License-Identifier: CC0-1.0
 
-use core::convert::TryFrom;
 use core::fmt;
 use core::str::FromStr;
 
diff --git a/bitcoin/src/psbt/map/output.rs b/bitcoin/src/psbt/map/output.rs
index 4f032019..1bfc3c2d 100644
--- a/bitcoin/src/psbt/map/output.rs
+++ b/bitcoin/src/psbt/map/output.rs
@@ -1,7 +1,5 @@
 // SPDX-License-Identifier: CC0-1.0
 
-use core::convert::TryFrom;
-
 use secp256k1::XOnlyPublicKey;
 use {core, secp256k1};
 
diff --git a/bitcoin/src/psbt/raw.rs b/bitcoin/src/psbt/raw.rs
index 85275835..c52a70fe 100644
--- a/bitcoin/src/psbt/raw.rs
+++ b/bitcoin/src/psbt/raw.rs
@@ -6,7 +6,6 @@
 //! <https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki>.
 //!
 
-use core::convert::TryFrom;
 use core::fmt;
 
 use super::serialize::{Deserialize, Serialize};
diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs
index 4dd7ea3d..92bef807 100644
--- a/bitcoin/src/psbt/serialize.rs
+++ b/bitcoin/src/psbt/serialize.rs
@@ -6,8 +6,6 @@
 //! according to the BIP-174 specification.
 //!
 
-use core::convert::{TryFrom, TryInto};
-
 use hashes::{hash160, ripemd160, sha256, sha256d, Hash};
 use secp256k1::{self, XOnlyPublicKey};
 
@@ -386,8 +384,6 @@ fn key_source_len(key_source: &KeySource) -> usize { 4 + 4 * (key_source.1).as_r
 
 #[cfg(test)]
 mod tests {
-    use core::convert::TryFrom;
-
     use super::*;
 
     // Composes tree matching a given depth map, filled with dumb script leafs,
diff --git a/bitcoin/src/taproot.rs b/bitcoin/src/taproot.rs
index 8e4dab06..d8877143 100644
--- a/bitcoin/src/taproot.rs
+++ b/bitcoin/src/taproot.rs
@@ -6,7 +6,6 @@
 //!
 
 use core::cmp::Reverse;
-use core::convert::TryFrom;
 use core::fmt;
 use core::iter::FusedIterator;
 
@@ -1845,7 +1844,7 @@ fn taptree_builder() {
         let tree_info = builder.finalize(&secp, internal_key).unwrap();
         let output_key = tree_info.output_key();
 
-        for script in vec![a, b, c, d, e] {
+        for script in [a, b, c, d, e] {
             let ver_script = (script, LeafVersion::TapScript);
             let ctrl_block = tree_info.control_block(&ver_script).unwrap();
             assert!(ctrl_block.verify_taproot_commitment(
diff --git a/clippy.toml b/clippy.toml
index 6fbdb48f..173999bc 100644
--- a/clippy.toml
+++ b/clippy.toml
@@ -1,2 +1,2 @@
-msrv = "1.48.0"
+msrv = "1.56.1"
 too-many-arguments-threshold = 13
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
index c40270cc..9abf5cd6 100644
--- a/fuzz/Cargo.toml
+++ b/fuzz/Cargo.toml
@@ -1,6 +1,7 @@
 [package]
 name = "bitcoin-fuzz"
-edition = "2018"
+edition = "2021"
+rust-version = "1.56.1"
 version = "0.0.1"
 authors = ["Generated by fuzz/generate-files.sh"]
 publish = false
diff --git a/fuzz/generate-files.sh b/fuzz/generate-files.sh
index 25af8989..18cba6a8 100755
--- a/fuzz/generate-files.sh
+++ b/fuzz/generate-files.sh
@@ -11,7 +11,8 @@ source "$REPO_DIR/fuzz/fuzz-util.sh"
 cat > "$REPO_DIR/fuzz/Cargo.toml" <<EOF
 [package]
 name = "bitcoin-fuzz"
-edition = "2018"
+edition = "2021"
+rust-version = "1.56.1"
 version = "0.0.1"
 authors = ["Generated by fuzz/generate-files.sh"]
 publish = false
diff --git a/hashes/Cargo.toml b/hashes/Cargo.toml
index 1238ab66..a68a0a70 100644
--- a/hashes/Cargo.toml
+++ b/hashes/Cargo.toml
@@ -9,7 +9,8 @@ description = "Hash functions used by the rust-bitcoin eccosystem"
 categories = ["algorithms"]
 keywords = [ "crypto", "bitcoin", "hash", "digest" ]
 readme = "README.md"
-edition = "2018"
+edition = "2021"
+rust-version = "1.56.1"
 exclude = ["tests", "contrib"]
 
 [features]
diff --git a/hashes/README.md b/hashes/README.md
index 809a173b..433a9593 100644
--- a/hashes/README.md
+++ b/hashes/README.md
@@ -9,7 +9,7 @@ since these are needed to display hashes anway.
 
 ## Minimum Supported Rust Version (MSRV)
 
-This library should always compile with any combination of features on **Rust 1.48.0**.
+This library should always compile with any combination of features on **Rust 1.56.1**.
 
 
 To build with the MSRV you will need to pin `serde` (if you have either the `serde` or the
diff --git a/hashes/embedded/Cargo.toml b/hashes/embedded/Cargo.toml
index 5d9644c4..bd3e388d 100644
--- a/hashes/embedded/Cargo.toml
+++ b/hashes/embedded/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 authors = ["Riccardo Casatta <riccardo@casatta.it>"]
-edition = "2018"
+edition = "2021"
 readme = "README.md"
 name = "embedded"
 version = "0.1.0"
diff --git a/hashes/src/sha1.rs b/hashes/src/sha1.rs
index 79eab8f5..0520ff34 100644
--- a/hashes/src/sha1.rs
+++ b/hashes/src/sha1.rs
@@ -102,10 +102,10 @@ fn process_block(&mut self) {
 
         for (i, &wi) in w.iter().enumerate() {
             let (f, k) = match i {
-                0...19 => ((b & c) | (!b & d), 0x5a827999),
-                20...39 => (b ^ c ^ d, 0x6ed9eba1),
-                40...59 => ((b & c) | (b & d) | (c & d), 0x8f1bbcdc),
-                60...79 => (b ^ c ^ d, 0xca62c1d6),
+                0..=19 => ((b & c) | (!b & d), 0x5a827999),
+                20..=39 => (b ^ c ^ d, 0x6ed9eba1),
+                40..=59 => ((b & c) | (b & d) | (c & d), 0x8f1bbcdc),
+                60..=79 => (b ^ c ^ d, 0xca62c1d6),
                 _ => unreachable!(),
             };
 
diff --git a/internals/Cargo.toml b/internals/Cargo.toml
index e9889dc0..ade1a5d6 100644
--- a/internals/Cargo.toml
+++ b/internals/Cargo.toml
@@ -9,7 +9,8 @@ description = "Internal types and macros used by rust-bitcoin ecosystem"
 categories = ["cryptography::cryptocurrencies"]
 keywords = ["internal"]
 readme = "README.md"
-edition = "2018"
+edition = "2021"
+rust-version = "1.56.1"
 exclude = ["tests", "contrib"]
 
 [features]
diff --git a/internals/build.rs b/internals/build.rs
index b5e2f5f6..15add3f3 100644
--- a/internals/build.rs
+++ b/internals/build.rs
@@ -1,4 +1,4 @@
-const MSRV_MINOR: u64 = 48;
+const MSRV_MINOR: u64 = 56;
 
 fn main() {
     let rustc = std::env::var_os("RUSTC");
diff --git a/internals/src/serde.rs b/internals/src/serde.rs
index 14c5a49c..de79756a 100644
--- a/internals/src/serde.rs
+++ b/internals/src/serde.rs
@@ -47,7 +47,6 @@ fn into_de_error<E: de::Error>(self, expected: Option<&dyn de::Expected>) -> E {
             })
         }
 
-        #[cfg(rust_v_1_55)]
         fn try_into_de_error<E>(self, expected: Option<&dyn de::Expected>) -> Result<E, Self>
         where
             E: de::Error,
@@ -61,13 +60,5 @@ fn try_into_de_error<E>(self, expected: Option<&dyn de::Expected>) -> Result<E,
                 _ => Err(self),
             }
         }
-
-        #[cfg(not(rust_v_1_55))]
-        fn try_into_de_error<E>(self, _expected: Option<&dyn de::Expected>) -> Result<E, Self>
-        where
-            E: de::Error,
-        {
-            Err(self)
-        }
     }
 }
diff --git a/rustfmt.toml b/rustfmt.toml
index 2c104735..93e688a2 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -57,7 +57,7 @@ trailing_comma = "Vertical"
 match_block_trailing_comma = false
 blank_lines_upper_bound = 1
 blank_lines_lower_bound = 0
-edition = "2018"
+edition = "2021"
 version = "One"
 inline_attribute_width = 0
 format_generated_files = true


Test patch:
diff --git a/bitcoin/tests/psbt.rs b/bitcoin/tests/psbt.rs
index 360be93d..7ad4bda5 100644
--- a/bitcoin/tests/psbt.rs
+++ b/bitcoin/tests/psbt.rs
@@ -1,7 +1,6 @@
 //! Tests PSBT integration vectors from BIP 174
 //! defined at <https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#test-vectors>
 
-use core::convert::TryFrom;
 use std::collections::BTreeMap;
 use std::str::FromStr;
 
diff --git a/contrib/test.sh b/contrib/test.sh
index 51abc82a..1e40fb1e 100755
--- a/contrib/test.sh
+++ b/contrib/test.sh
@@ -4,22 +4,6 @@ set -ex
 
 CRATES="bitcoin hashes internals fuzz"
 DEPS="recent minimal"
-MSRV="1\.48\.0"
-
-# Test pinned versions.
-if cargo --version | grep ${MSRV}; then
-    cargo update -p serde_json --precise 1.0.99
-    cargo update -p serde --precise 1.0.156
-    cargo update -p quote --precise 1.0.30
-    cargo update -p proc-macro2 --precise 1.0.63
-    cargo update -p serde_test --precise 1.0.175
-    cargo update -p schemars --precise 0.8.12
-    # byteorder 1.5.0 uses edition 2021
-    cargo update -p byteorder --precise 1.4.3
-
-    # Build MSRV with pinned versions.
-    cargo check --all-features --all-targets
-fi
 
 for dep in $DEPS
 do
diff --git a/hashes/extended_tests/schemars/Cargo.toml b/hashes/extended_tests/schemars/Cargo.toml
index 8a8943d2..d25cec04 100644
--- a/hashes/extended_tests/schemars/Cargo.toml
+++ b/hashes/extended_tests/schemars/Cargo.toml
@@ -2,7 +2,7 @@
 name = "schemars"
 version = "0.1.0"
 authors = ["Jeremy Rubin <j@rubin.io>"]
-edition = "2018"
+edition = "2021"
 
 # Prevent this from interfering with workspaces
 [workspace]