Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
068c3f2
Fix `is_invalid_use_of_sighash_single()` incompatibility with Bitcoin…
liuchengxu Feb 24, 2025
18c2cad
Add test for sighash_single_bug incompatility fix
liuchengxu Feb 24, 2025
2c97c79
Merge rust-bitcoin/rust-bitcoin#4122: backport: Fix `is_invalid_use_o…
apoelstra Feb 28, 2025
39e280a
Fix key/script spend detection in `Witness`
Kixunil Feb 21, 2025
74138d5
Add a test case checking `taproot_control_block`
Kixunil Feb 21, 2025
730baeb
Add `taproot_leaf_script` methood to `Witness`
Kixunil Feb 21, 2025
9e87bc5
Deprecate the `Witness::tapscript` method
Kixunil Feb 21, 2025
30fbc0f
Merge rust-bitcoin/rust-bitcoin#4101: Backport witness fixes
apoelstra Mar 9, 2025
315750d
bip32: return error when attempting to derive past maximum depth
apoelstra May 3, 2025
b75b2e3
Fix GetKey for sets to properly compare the fingerprint
shesek Sep 13, 2024
d005ddd
Refactor GetKey for sets to internally use Xpriv::get_key()
shesek Sep 13, 2024
d8a6b9f
Merge rust-bitcoin/rust-bitcoin#4434: [backport 0.32.x] bip32: return…
apoelstra May 5, 2025
2858b6c
Support GetKey where the Xpriv is a direct child of the looked up Key…
shesek Sep 13, 2024
95eb255
Add XOnlyPublicKey support for PSBT key retrieval and improve Taproot…
erickcestari Mar 14, 2025
c67adcd
backport: Add methods to retrieve inner types
shinghim Apr 20, 2025
f4fac15
Merge rust-bitcoin/rust-bitcoin#4450: backport: Add methods to retrie…
apoelstra May 7, 2025
2044697
Merge rust-bitcoin/rust-bitcoin#4443: backport: Add XOnlyPublicKey su…
apoelstra May 8, 2025
916982a
bitcoin: Bump version to 0.32.6
tcharding May 5, 2025
7ff26ac
Merge rust-bitcoin/rust-bitcoin#4453: Release tracking PR: `bitcoin 0…
apoelstra May 13, 2025
c7b20f4
backport: Use _u32 in FeeRate constructor instead of _unchecked
tcharding May 24, 2025
944feb9
Merge rust-bitcoin/rust-bitcoin#4552: backport: Use _u32 in FeeRate c…
apoelstra May 24, 2025
c2481e4
backport: Add support for pay to anchor outputs
tcharding Jul 8, 2025
d31d17e
Merge rust-bitcoin/rust-bitcoin#4691: backport: Add support for pay t…
apoelstra Jul 16, 2025
3cf4a91
Remove non_exhausive from Network
tcharding Jul 1, 2025
db7a238
Merge rust-bitcoin/rust-bitcoin#4658: backport to `v0.32`: Remove `no…
apoelstra Jul 28, 2025
571cd7f
bitcoin: Bump version to 0.32.7
tcharding Jul 30, 2025
8aec240
Merge rust-bitcoin/rust-bitcoin#4740: Release tracking PR: `bitcoin 0…
apoelstra Aug 4, 2025
d4a2b53
Merge tag 'bitcoin-0.32.7' into mducroux/dogecoin-v0.32.7
mducroux Dec 23, 2025
f835efc
update lock files
mducroux Dec 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions Cargo-minimal.lock
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ checksum = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"

[[package]]
name = "cfg-if"
version = "1.0.0"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"

[[package]]
name = "cipher"
Expand All @@ -176,9 +176,9 @@ dependencies = [

[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
Expand Down Expand Up @@ -292,9 +292,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"

[[package]]
name = "libc"
version = "0.2.172"
version = "0.2.178"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"

[[package]]
name = "memmap2"
Expand Down Expand Up @@ -548,7 +548,7 @@ version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"cpufeatures",
"digest",
]
Expand All @@ -572,9 +572,9 @@ dependencies = [

[[package]]
name = "typenum"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"

[[package]]
name = "unicode-ident"
Expand Down
12 changes: 6 additions & 6 deletions Cargo-recent.lock
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,9 @@ dependencies = [

[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
Expand Down Expand Up @@ -285,9 +285,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"

[[package]]
name = "libc"
version = "0.2.172"
version = "0.2.178"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"

[[package]]
name = "memmap2"
Expand Down Expand Up @@ -555,9 +555,9 @@ dependencies = [

[[package]]
name = "typenum"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"

[[package]]
name = "unicode-ident"
Expand Down
14 changes: 14 additions & 0 deletions bitcoin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

# 0.32.7 - 2025-07-30

- Backport - Use `_u32` in `FeeRate` constructor instead of `_unchecked` [#4552](https://github.com/rust-bitcoin/rust-bitcoin/pull/4552)
- Backport - Add support for pay to anchor outputs [#4691](https://github.com/rust-bitcoin/rust-bitcoin/pull/4691)
- Backport - Remove `non_exhaustive` from `Network` [#4658](https://github.com/rust-bitcoin/rust-bitcoin/pull/4658)

# 0.32.6 - 2025-05-06

- Backport - Fix `is_invalid_use_of_sighash_single()` incompatibility with Bitcoin Core [#4122](https://github.com/rust-bitcoin/rust-bitcoin/pull/4122)
- Backport - Backport witness fixes [#4101](https://github.com/rust-bitcoin/rust-bitcoin/pull/4101)
- Backport - bip32: Return error when attempting to derive past maximum depth [#4434](https://github.com/rust-bitcoin/rust-bitcoin/pull/4434)
- Backport - Add `XOnlyPublicKey` support for PSBT key retrieval and improve Taproot signing [#4443](https://github.com/rust-bitcoin/rust-bitcoin/pull/4443)
- Backport - Add methods to retrieve inner types [#4450](https://github.com/rust-bitcoin/rust-bitcoin/pull/4450)

# 0.32.5-doge.1 - 2025-11-10

- Fix build doc on [docs.rs](https://docs.rs/crate/bitcoin-dogecoin/latest)
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@ required-features = ["std", "rand-std", "bitcoinconsensus"]
name = "sighash"

[lints.rust]
unexpected_cfgs = { level = "deny", check-cfg = ['cfg(bench)', 'cfg(fuzzing)', 'cfg(kani)', 'cfg(mutate)', 'cfg(rust_v_1_60)'] }
unexpected_cfgs = { level = "deny", check-cfg = ['cfg(bench)', 'cfg(fuzzing)', 'cfg(kani)', 'cfg(mutate)', 'cfg(rust_v_1_60)', 'cfg(rust_v_1_61)'] }
2 changes: 1 addition & 1 deletion bitcoin/examples/sign-tx-taproot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fn main() {
// Sign the sighash using the secp256k1 library (exported by rust-bitcoin).
let tweaked: TweakedKeypair = keypair.tap_tweak(&secp, None);
let msg = Message::from(sighash);
let signature = secp.sign_schnorr(&msg, &tweaked.to_inner());
let signature = secp.sign_schnorr(&msg, tweaked.as_keypair());

// Update the witness stack.
let signature = bitcoin::taproot::Signature { signature, sighash_type };
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/examples/taproot-psbt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ fn sign_psbt_taproot(
) {
let keypair = secp256k1::Keypair::from_seckey_slice(secp, secret_key.as_ref()).unwrap();
let keypair = match leaf_hash {
None => keypair.tap_tweak(secp, psbt_input.tap_merkle_root).to_inner(),
None => keypair.tap_tweak(secp, psbt_input.tap_merkle_root).to_keypair(),
Some(_) => keypair, // no tweak for script spend
};

Expand Down
24 changes: 24 additions & 0 deletions bitcoin/src/address/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ pub enum AddressType {
P2wsh,
/// Pay to taproot.
P2tr,
/// Pay to anchor.
P2a
}

impl fmt::Display for AddressType {
Expand All @@ -84,6 +86,7 @@ impl fmt::Display for AddressType {
AddressType::P2wpkh => "p2wpkh",
AddressType::P2wsh => "p2wsh",
AddressType::P2tr => "p2tr",
AddressType::P2a => "p2a",
})
}
}
Expand All @@ -97,6 +100,7 @@ impl FromStr for AddressType {
"p2wpkh" => Ok(AddressType::P2wpkh),
"p2wsh" => Ok(AddressType::P2wsh),
"p2tr" => Ok(AddressType::P2tr),
"p2a" => Ok(AddressType::P2a),
_ => Err(UnknownAddressTypeError(s.to_owned())),
}
}
Expand Down Expand Up @@ -496,6 +500,8 @@ impl Address {
Some(AddressType::P2wsh)
} else if program.is_p2tr() {
Some(AddressType::P2tr)
} else if program.is_p2a() {
Some(AddressType::P2a)
} else {
None
},
Expand Down Expand Up @@ -1367,4 +1373,22 @@ mod tests {
}
}
}

#[test]
fn pay_to_anchor_address_regtest() {
// Verify that p2a uses the expected address for regtest.
// This test-vector is borrowed from the bitcoin source code.
let address_str = "bcrt1pfeesnyr2tx";

let script = ScriptBuf::new_p2a();
let address_unchecked = address_str.parse().unwrap();
let address = Address::from_script(&script, Network::Regtest).unwrap();
assert_eq!(address.as_unchecked(), &address_unchecked);
assert_eq!(address.to_string(), address_str);

// Verify that the address is considered standard
// and that the output type is P2a
assert!(address.is_spend_standard());
assert_eq!(address.address_type(), Some(AddressType::P2a));
}
}
13 changes: 11 additions & 2 deletions bitcoin/src/bip32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ impl ChildNumber {

/// Returns the child number that is a single increment from this one.
pub fn increment(self) -> Result<ChildNumber, Error> {
// Bare addition in this function is okay, because we have an invariant that
// `index` is always within [0, 2^31 - 1]. FIXME this is not actually an
// invariant because the fields are public.
match self {
ChildNumber::Normal { index: idx } => ChildNumber::from_normal_idx(idx + 1),
ChildNumber::Hardened { index: idx } => ChildNumber::from_hardened_idx(idx + 1),
Expand Down Expand Up @@ -481,6 +484,10 @@ pub type KeySource = (Fingerprint, DerivationPath);
pub enum Error {
/// A pk->pk derivation was attempted on a hardened key
CannotDeriveFromHardenedKey,
/// Attempted to derive a child of depth 256 or higher.
///
/// There is no way to encode such xkeys.
MaximumDepthExceeded,
/// A secp256k1 error occurred
Secp256k1(secp256k1::Error),
/// A child number was provided that was out of range
Expand Down Expand Up @@ -512,6 +519,7 @@ impl fmt::Display for Error {
match *self {
CannotDeriveFromHardenedKey =>
f.write_str("cannot derive hardened key from public key"),
MaximumDepthExceeded => f.write_str("cannot derive child of depth 256 or higher"),
Secp256k1(ref e) => write_err!(f, "secp256k1 error"; e),
InvalidChildNumber(ref n) =>
write!(f, "child number {} is invalid (not within [0, 2^31 - 1])", n),
Expand Down Expand Up @@ -540,6 +548,7 @@ impl std::error::Error for Error {
Hex(ref e) => Some(e),
InvalidBase58PayloadLength(ref e) => Some(e),
CannotDeriveFromHardenedKey
| MaximumDepthExceeded
| InvalidChildNumber(_)
| InvalidChildNumberFormat
| InvalidDerivationPathFormat
Expand Down Expand Up @@ -636,7 +645,7 @@ impl Xpriv {

Ok(Xpriv {
network: self.network,
depth: self.depth + 1,
depth: self.depth.checked_add(1).ok_or(Error::MaximumDepthExceeded)?,
parent_fingerprint: self.fingerprint(secp),
child_number: i,
private_key: tweaked,
Expand Down Expand Up @@ -768,7 +777,7 @@ impl Xpub {

Ok(Xpub {
network: self.network,
depth: self.depth + 1,
depth: self.depth.checked_add(1).ok_or(Error::MaximumDepthExceeded)?,
parent_fingerprint: self.fingerprint(),
child_number: i,
public_key: tweaked,
Expand Down
12 changes: 9 additions & 3 deletions bitcoin/src/blockdata/script/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use secp256k1::{Secp256k1, Verification};

use crate::blockdata::opcodes::all::*;
use crate::blockdata::opcodes::{self, Opcode};
use crate::blockdata::script::witness_program::WitnessProgram;
use crate::blockdata::script::witness_program::{WitnessProgram, P2A_PROGRAM};
use crate::blockdata::script::witness_version::WitnessVersion;
use crate::blockdata::script::{
opcode_to_verify, Builder, Instruction, PushBytes, Script, ScriptHash, WScriptHash,
Expand Down Expand Up @@ -130,6 +130,11 @@ impl ScriptBuf {
ScriptBuf::new_witness_program_unchecked(WitnessVersion::V1, output_key.serialize())
}

/// Generates pay to anchor output.
pub fn new_p2a() -> Self {
ScriptBuf::new_witness_program_unchecked(WitnessVersion::V1, P2A_PROGRAM)
}

/// Generates P2WSH-type of scriptPubkey with a given [`WitnessProgram`].
pub fn new_witness_program(witness_program: &WitnessProgram) -> Self {
Builder::new()
Expand All @@ -141,14 +146,15 @@ impl ScriptBuf {
/// Generates P2WSH-type of scriptPubkey with a given [`WitnessVersion`] and the program bytes.
/// Does not do any checks on version or program length.
///
/// Convenience method used by `new_p2wpkh`, `new_p2wsh`, `new_p2tr`, and `new_p2tr_tweaked`.
/// Convenience method used by `new_p2wpkh`, `new_p2wsh`, `new_p2tr`, and `new_p2tr_tweaked`,
/// and `new_p2a`.
pub(crate) fn new_witness_program_unchecked<T: AsRef<PushBytes>>(
version: WitnessVersion,
program: T,
) -> Self {
let program = program.as_ref();
debug_assert!(program.len() >= 2 && program.len() <= 40);
// In segwit v0, the program must be 20 or 32 bytes long.
// In SegWit v0, the program must be either 20 (P2WPKH) bytes or 32 (P2WSH) bytes long
debug_assert!(version != WitnessVersion::V0 || program.len() == 20 || program.len() == 32);
Builder::new().push_opcode(version.into()).push_slice(program).into_script()
}
Expand Down
19 changes: 17 additions & 2 deletions bitcoin/src/blockdata/script/witness_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub const MIN_SIZE: usize = 2;
/// The maximum byte size of a segregated witness program.
pub const MAX_SIZE: usize = 40;

/// The P2A program which is given by 0x4e73.
pub(crate) const P2A_PROGRAM: [u8;2] = [78, 115];

/// The segregated witness program.
///
/// The segregated witness program is technically only the program bytes _excluding_ the witness
Expand Down Expand Up @@ -90,16 +93,23 @@ impl WitnessProgram {
merkle_root: Option<TapNodeHash>,
) -> Self {
let (output_key, _parity) = internal_key.tap_tweak(secp, merkle_root);
let pubkey = output_key.to_inner().serialize();
let pubkey = output_key.as_x_only_public_key().serialize();
WitnessProgram::new_p2tr(pubkey)
}

/// Creates a pay to taproot address from a pre-tweaked output key.
pub fn p2tr_tweaked(output_key: TweakedPublicKey) -> Self {
let pubkey = output_key.to_inner().serialize();
let pubkey = output_key.as_x_only_public_key().serialize();
WitnessProgram::new_p2tr(pubkey)
}

internals::const_tools::cond_const! {
/// Constructs a new pay to anchor address
pub const(in rust_v_1_61 = "1.61") fn p2a() -> Self {
WitnessProgram { version: WitnessVersion::V1, program: ArrayVec::from_slice(&P2A_PROGRAM)}
}
}

/// Returns the witness program version.
pub fn version(&self) -> WitnessVersion { self.version }

Expand All @@ -123,6 +133,11 @@ impl WitnessProgram {

/// Returns true if this witness program is for a P2TR output.
pub fn is_p2tr(&self) -> bool { self.version == WitnessVersion::V1 && self.program.len() == 32 }

/// Returns true if this is a pay to anchor output.
pub fn is_p2a(&self) -> bool {
self.version == WitnessVersion::V1 && self.program == P2A_PROGRAM
}
}

/// Witness program error.
Expand Down
Loading