Repository navigation
Conversation
Source: rust-miniscript 3d9acd2 Co-authored-by: Nadav Ivgi <nadav@shesek.info>
Port of upstream "Support conversion of multi-Xprivs into multi-Xpubs"
Upstream PR #757 also has ae64ce6 ("Some minor formatting changes"),
which only reformats the origin matches of the two to_public functions.
It is not ported: our key.rs keeps its own formatting, and this commit
takes the 7d3e1e8 code as it was before that reformat.
Source: rust-miniscript 7d3e1e8
Co-authored-by: Nadav Ivgi <nadav@shesek.info>
Port of upstream "refactor: make descriptors::key::DescriptorKeyParseError an enum" This is a prerequisite of the NonDefiniteKeyError port: upstream adds DescriptorKeyParseError::NonDefiniteKey and MalformedKeyDataKind::MaximumDepthExceeded to these enums. Elements adaptations: - The hex private key of a ct() view key, which upstream does not parse, is reported with a new Elements-only DescriptorKeyParseError::HexPrivateKey variant. The key is parsed with secp256k1::SecretKey::from_str, so that one error type covers both bad hex and an invalid secret key. - The confidential_descriptor_invalid test expects the new "key too short" message. Source: rust-miniscript 497c5a3 Co-authored-by: Chris Ricketts <chris_ricketts@protonmail.com>
Port of upstream "descriptor/key.rs: clean up error matching". Source: rust-miniscript bd5db6a Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "key.rs: split "definite keys cannot have wildcards" into own error" Source: rust-miniscript 258873f Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "DefiniteDescriptorKey: disallow multipath keys" Elements adaptation: our DefiniteDescriptorKey::new was private and returned Option. Upstream's was already public, so make it public with the upstream signature, Result<Self, NonDefiniteKeyError>. Source: rust-miniscript dad3532 Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "descriptor: add unit tests for constructing multipath keys" Source: rust-miniscript b9ccd9d Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "key: fix DefiniteDescriptorKey construction from key with hardened step" Adaptations: - Upstream still has `expect` on the constructor result in DescriptorPublicKey::at_derivation_index, so it panics on a hardened step until 97c948d. Here at_derivation_index maps the error to ConversionError::HardenedChild instead, so that no commit in this series panics where the previous one returned an error. The ports of 4930ccb and 97c948d replace the mapping. - Key::to_public_key in the confidential module propagates the at_derivation_index error for bare and view blinding keys instead of expecting success. - descriptor_hardened_wildcard_blinding_key: a ct() descriptor whose bare blinding key has a hardened wildcard now fails in at_derivation_index rather than in address(), so the test asserts that error. Source: rust-miniscript 7b3b3a8 Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "key.rs: remove some deprecated methods" Source: rust-miniscript 77ed78b Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "key.rs: remove a bunch of unwrap()s which are impossible".
Elements adaptations, to callers rather than to the API:
- psbt: KeySourceLookUp translates with core::convert::Infallible and expects full_derivation_path, as upstream does.
Our Tr and TrExt helper, which upstream does not have, does the same and no longer returns a Result.
update_item_with_descriptor_helper keeps its Result, as upstream does, with an allow for clippy::unnecessary_wraps, a lint that our Cargo.toml enables and upstream's does not.
- The derived descriptor translators match the Infallible error away, because our translate_pk returns the translator error directly rather than upstream's TranslateErr.
- Pegin::derived_descriptor, confidential Key::to_public_key, the xpub_descriptors example and the bitcoind-tests no longer handle an error from these calls.
Upstream PR #839 also has e1f0802 ("macros: make target pk and error type optional for translate_* macros") and 6267818 ("TranslateErr: add helper function to unwrap impossible case").
They are not ported.
Both build on upstream's Translator trait with associated TargetPk and Error types and on its TranslateErr wrapper, which our fork does not have:
our Translator<P, Q, E> takes the types as parameters, and translate_pk returns E directly.
So this commit names all three types in translate_hash_clone!, and matches the Infallible error away where upstream unwraps a TranslateErr.
Source: rust-miniscript c169af0
Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "psbt: remove derives from UtxoUpdateError and OutputUpdateError". Source: rust-miniscript 627d963 Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "key: replace ConversionError with NonDefiniteKeyError". Elements adaptations, to callers of the API: - Error::Conversion(ConversionError) becomes Error::NonDefiniteKey(NonDefiniteKeyError). Upstream's Error has no such variant, but ours is how confidential and pegin code report a key that cannot be derived. - confidential::Descriptor::at_derivation_index returns NonDefiniteKeyError: HardenedStep for a hardened index on an xprv view key and Multipath for a multipath view key. - DescriptorPublicKey::at_derivation_index returns the result of DefiniteDescriptorKey::new directly, where upstream still expects it until 97c948d. The previous commits mapped that result to ConversionError instead of expecting it, so this keeps the series free of new panics. Source: rust-miniscript 4930ccb Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Port of upstream "fuzz: add fuzz test for parsing definite descriptor keys". Adaptations: the target imports elements_miniscript as miniscript, as the other targets do, and computes the address with AddressParams::ELEMENTS instead of Network::Bitcoin. Upstream's workflow file is cron-daily-fuzz.yml. Ours is fuzz.yml. Source: rust-miniscript f09bf48 Co-authored-by: Andrew Poelstra <apoelstra@wpsoftware.net>
Partial port of upstream "feat: add new functions on DescriptorPublicKey" (doc line only) Source: rust-miniscript 4906bed (partial: doc line only) Co-authored-by: Trevor Arjeski <tmarjeski@gmail.com>
Port of upstream "Fix hardened derivation path error handling in `at_derivation_index`". Source: rust-miniscript 97c948d Co-authored-by: Velnbur <kyrylobaybula@gmail.com>
Port of upstream "descriptor: reject definite keys deeper than BIP32 allows". Adaptations, because our fork lacks upstream 1062144, which added Descriptor::into_definite and deprecated at_derivation_index: - The last check of the definite_key_maximum_depth test calls at_derivation_index(0) where upstream calls into_definite(). Both go through DefiniteDescriptorKey::new, so they check the same thing. The descriptor is built with Descriptor::<DescriptorPublicKey>::new_tr. - The depth line that upstream adds to the into_definite and derive_at_index docs goes on our Descriptor::at_derivation_index. Source: rust-miniscript 613ed0d Co-authored-by: Boris Nagaev <bnagaev@gmail.com>
Port of upstream "descriptor: reject keys deeper than BIP32 allows when parsing". Adaptations: - Our xprv check sits in DescriptorSecretKey::from_str_inner, so it also covers the xprv view key of a ct() descriptor. - The test descriptor is eltr() instead of tr(). Source: rust-miniscript f2862f7 Co-authored-by: Boris Nagaev <bnagaev@gmail.com>
KyrylR
commented
Nov 11, 2026
Comment on lines
+16
to
25
| - Breaking: `DescriptorKeyParseError` is a `#[non_exhaustive]` enum instead of a struct holding a string, and no longer derives `Copy`. The new `MalformedKeyDataKind` enum describes malformed key data. Messages start with a lowercase letter and follow rust-miniscript. The Elements-only `HexPrivateKey` variant reports a bad hex view key in a `ct()` descriptor. Ported from rust-miniscript 497c5a3 and bd5db6a. | ||
| - Breaking: `ConversionError` is replaced by the `#[non_exhaustive]` `NonDefiniteKeyError`, with `Wildcard`, `Multipath`, `HardenedStep` and `MaximumDepthExceeded` variants. It is returned by `DefiniteDescriptorKey::new`, `DescriptorPublicKey::at_derivation_index`, `Descriptor::at_derivation_index`, `Descriptor::derived_descriptor`, `Descriptor::find_derivation_index_for_spk`, `confidential::Descriptor::at_derivation_index` and the PSET `update_with_descriptor_unchecked` methods, and held by `UtxoUpdateError::DerivationError` and `OutputUpdateError::DerivationError`. `Error::Conversion` becomes `Error::NonDefiniteKey`. Ported from rust-miniscript 258873f, dad3532, 7b3b3a8, 4930ccb and 613ed0d. | ||
| - Breaking: `DefiniteDescriptorKey::new` is public and returns `Result<Self, NonDefiniteKeyError>`. Keys with a wildcard were already rejected. It now also rejects a hardened derivation step after an xpub (`HardenedStep`), several derivation paths (`Multipath`), and a derivation deeper than BIP32's maximum depth of 255 (`MaximumDepthExceeded`), checked in the order wildcard, hardened step, multipath, depth. `DescriptorPublicKey::at_derivation_index`, and the descriptor methods built on it, return the same errors. `DefiniteDescriptorKey::from_str` wraps them in `DescriptorKeyParseError::NonDefiniteKey`, so `Descriptor::<DefiniteDescriptorKey>::from_str` now rejects hardened and multipath keys, which previously parsed and panicked when derived, for example in `script_pubkey`. A `ct()` descriptor whose bare blinding key has a hardened wildcard now fails in `at_derivation_index` instead of `address`. Ported from rust-miniscript dad3532, 7b3b3a8, 97c948d and 613ed0d. | ||
| - Parsing an xpub or xprv whose derivation goes deeper than BIP32's maximum depth of 255 fails with `DescriptorKeyParseError::MalformedKeyData(MalformedKeyDataKind::MaximumDepthExceeded)`, so such a string never reaches the constructor. A wildcard or multipath step counts as one step, and origin steps don't count. The constructor's `NonDefiniteKeyError::MaximumDepthExceeded` is only returned for keys built in code. Ported from rust-miniscript f2862f7. | ||
| - Breaking: `DefiniteDescriptorKey::derive_public_key` returns a `bitcoin::PublicKey` and `Descriptor::<DefiniteDescriptorKey>::derived_descriptor` returns a descriptor, instead of a `Result`. Ported from rust-miniscript c169af0. | ||
| - Breaking: the deprecated `DescriptorPublicKey::is_deriveable`, `DescriptorPublicKey::derive`, `Descriptor::is_deriveable` and `Descriptor::derive` are removed. Use `has_wildcard` and `at_derivation_index`. Ported from rust-miniscript 77ed78b. | ||
| - Breaking: `UtxoUpdateError` and `OutputUpdateError` derive only `Debug`, `PartialEq`, `Eq` and `Clone`. `NonDefiniteKeyError`, `MalformedKeyDataKind` and `DescriptorKeyParseError` derive `Eq`. Ported from rust-miniscript 627d963. | ||
| - Add `DescriptorPublicKey::has_hardened_step`. Ported from rust-miniscript 7b3b3a8 and, for its doc line, 4906bed (partial). | ||
| - `DescriptorSecretKey::to_public` converts a multi-xpriv into a multi-xpub when all hardened derivation steps are shared among its paths, instead of always failing. Ported from rust-miniscript 7d3e1e8. | ||
|
|
Contributor
Author
There was a problem hiding this comment.
There is no way around with this changelog
Maybe the reorg will help, but the total number of already introduced changes does not help
Will be grateful for the advice regarding this
Contributor
Author
|
If/when this merged I will be able to fully resolve the #107 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Created this PR with a help of GPT Astra, Opus 5.5, and Mythos 5.1
All commits except the one for the CHANGELOG are cherry-picked from the https://git.rust-bitcoin.org/rust-bitcoin/rust-miniscript/ (all of them has Source: rust-miniscript and the related author)
This work intends to simplify future forward port of elements-miniscript into rust-miniscript and current work on porting the taproot into the elements-miniscript project
Part of #107. Next step of the migration in #108: this brings our key code back in line with https://git.rust-bitcoin.org/rust-bitcoin/rust-miniscript/ master (d57bb31)
Ported commits (AI helped with creating a summary below)
at_derivation_indexDescriptorKeyParseErroran enumNonDefiniteKeyErrorfor wildcard keysis_deriveable/deriveConversionErrorwithNonDefiniteKeyErrorhas_hardened_stepat_derivation_indexNot ported:
TranslatorandTranslateErr. 6267818 is ported in the follow-up translate PR.Display for Wildcard.into_definite,derive_at_indexandNoWildcard. This would move every Elements caller ofat_derivation_index, so it belongs in its own PR. Tests that callinto_definite()upstream useat_derivation_index(0)here, which goes through the sameDefiniteDescriptorKey::new.Breaking changes
ConversionErroris replaced byNonDefiniteKeyError(Wildcard,Multipath,HardenedStep,MaximumDepthExceeded). The error type changes for:at_derivation_index(descriptor, key andconfidential::Descriptor)derived_descriptor(secp, index)find_derivation_index_for_spkError::Conversion, which is nowError::NonDefiniteKeyDefiniteDescriptorKey::newis public. Hardened, multipath and over-deep keys can no longer become definite, andDefiniteDescriptorKey::from_strrejects them.DescriptorKeyParseErroris a#[non_exhaustive]enum, no longerCopy, with lowercase messages as upstream. It has one Elements-only variant,HexPrivateKey, forct()hex view keys.derive_public_keyandDescriptor<DefiniteDescriptorKey>::derived_descriptorreturn values, notResults.is_deriveableandderiveare removed.UtxoUpdateErrorandOutputUpdateErrorderive onlyDebug, PartialEq, Eq, Clone.ct()descriptor whose bare blinding key has a hardened wildcard now fails inat_derivation_indexinstead ofaddress.Remaining differences from upstream master
None of these is introduced by this PR. They come from upstream commits outside its scope, or from Elements-only code.
into_definite/derive_at_index/NoWildcard(1062144, a15ce35).XKeyParseErrororUnexpectedXPrivateKey. Public-key parsing dispatches oncontains("pub")rather than the key prefix (15e3465, 945adb7, d7deb69).[fingerprint/path]origin (9416098 not ported).full_derivation_paths,derivation_path(s),wildcard,xkey_network,DerivPaths::single, andFrom<PublicKey>/From<XOnlyPublicKey>forDescriptorPublicKey.no_stdsupport (std::errorinstead ofcoreand the prelude).Self::paths are not used (7063e4a).Wildcard::Hardeneddoc says "Unhardened wildcard".DescriptorKeyParseError::HexPrivateKey.Error::NonDefiniteKey.derived_descriptorends withErr(e) => match e {}onInfallible, since ourtranslate_pkhas noTranslateErryet.Resultwith#[allow(clippy::unnecessary_wraps)], because ourCargo.tomlenables that lint.elements_miniscriptandAddressParams::ELEMENTS.derive_public_keyandderived_descriptordocs still describe errors these functions can no longer return.NonDefiniteKeyErroris documented as "Kinds of malformed key data", and its messages say "DerivedDescriptorKey".fmt_derivation_pathspanics on a multipath key built in code with paths of different lengths.parse_xkey_derivexpands multipath alternatives before the depth check.into_single_descriptorstakes the path count from the first multipath key.Testing
cargo test --all-features,cargo check --workspace --all-targets --all-featuresand nightly-2025-08-19 clippy with-D warningspass. Library tests go from 139 to 143.cargo doc -D warningsbitcoind-testsand the fuzz crate, including the new target, compilebitcoind-testsintegration run and honggfuzz.cargo +nightly-2025-08-19 fmt --all -- --checkreports 48 hunks, against 39 on master. Master isn't fmt-clean and CI has no fmt job.