Release notes¶
Notable changes are documented here. CHANGELOG.md is the record behind them: this file says what a user has to act on, that one says what changed.
Versions are calendar versions, YYYY.M.D: the
number says when a release was cut, and promises nothing about
compatibility, so a breaking change is announced in this file — read it
before upgrading, rather than a digit.
v2026.11.2¶
The wallet raises its own
FetchError,HttpError,RpcError,SignerError,SignerNotFoundError,InconclusiveErrorandNoDescriptorError, declared inbtclib_wallet.exceptions(issue btclib-org/btclib#2709). It raised btclib’s classes of the same names, frombtclib.exceptions. Each derives from the same btclib class as before,BTClibRuntimeErrororBTClibValueError, soexcept BTClibExceptionstill catches it. Act on it if you catch one of them imported frombtclib.exceptions: import it frombtclib_wallet.exceptions.TcpPeerTransportstill raisesbitcoin_core_rpc.FetchError, as it did before;CompactFilterFetcherraises the wallet’s.The Electrum codec is
btclib_wallet.electrum(issue btclib-org/btclib#2709).ElectrumFetcheruses it in place ofbtclib.electrum, soget_tx_merklereturns abtclib_wallet.electrum.MerkleProof. Act on it if you importbtclib.electrum, or check that proof’s type against btclib’s class: usebtclib_wallet.electrum.CompactFilterFetcherchecks the filter headers it is served against more peers (ISS 352). It takes them ascross_check, none by default, and compares theircfcheckptandcfheaderswith thosetransportserves, as BIP157’s Client Operation recommends. At the first disagreement it downloads the block, and drops a peer whose filter does not match its own header or leaves out one of the block’s output scripts. Where two filters differ only in the scripts the block’s inputs spend, the call fails withFetchError, naming that peer’s index incross_check, and drops no peer.transportis a read-only property, the peer that serves the chain: when that peer is dropped, the first peer ofcross_checktakes its place. Act on it if you assigntransport: build a new fetcher.TcpPeerTransport.closeraises a failed socket close asbitcoin_core_rpc.FetchError, as itssendandreceiveraise theirs, where it raised theOSError. Act on it if you catch thatOSError: catchbitcoin_core_rpc.FetchError.HistoryReaderlists the transactions that pay to or spend from some scripts (ISS 629). It is a protocol ofbtclib_wallet.fetch, besideBroadcaster,FeeEstimatorandBalanceReader.BitcoinCoreFetcherimplements it asget_history, without the node’s wallet; the other fetchers do not.CompactFilterFetcher.scan_blocksrefuses an empty script withBTClibValueError,an empty script to look for, where it looked for it. Act on it if you pass an empty script: leave it out.scan_outputsandscan_transaction_outputsrefuse a malformed label (ISS 474). A label that is not 33 bytes, a label tweak that is not 32 bytes in [1, n-1], and labels that are not a mapping are refused withBTClibValueErrororBTClibTypeError, whether or not the label matches.scan_outputs, andscan_transaction_outputswithout thesecp256k1extra, ignored an unmatched one and raisedAttributeErrorfor labels that are not a mapping. With the extra,scan_transaction_outputsrefused them already, raising a plainTypeErrorwhere it raisesBTClibTypeError, aTypeErrortoo.scan_transaction_outputsruns the Python scan with at most three labels or at least ten outputs per label, and otherwise calls the bindings where they serve;scan_outputsalways runs the Python scan. Act on it if you pass labels of your own making: passlabel_lookup’s map.A
tr()branch with any count of subtrees but two reports a fault in the subtrees read before the count (ISS 608).parsereads the first subtree, and the second where a comma follows the first, before it refuses the count, as Core does. A bad key or leaf among them raises its own refusal, such asinvalid key expressionortr() leaf is not a valid descriptor function, where it raiseda tr() branch takes two subtrees, <n> given. Act on it if you match that refusal: match the new message.
btclib’s main no longer declares the seven exceptions or
btclib.electrum, and its next release waits for this one, the first
that does not import them from btclib (issue btclib-org/btclib#2709).
CHANGELOG.md’s own v2026.11.2 section has the rest.
v2026.10.31¶
A descriptor no longer writes itself into a psbt:
update_psbt_inputandupdate_psbt_outputare functions ofbtclib_wallet.psbt(ISS 620).descriptor.update_psbt_input(psbt, vin_i, index, prv_keys)becomesupdate_psbt_input(descriptor, psbt, vin_i, index, prv_keys), and the same forupdate_psbt_output, on every descriptor class:Descriptor,PkDescriptor,PkhDescriptor,WpkhDescriptor,ShDescriptor,WshDescriptor,MiniscriptDescriptor,MultiDescriptor,ComboDescriptor,AddrDescriptor,RawDescriptor,TrDescriptorandRawTrDescriptor. The newDescriptor.expansion(index, prv_keys)returns theExpansionthey write. The checks run in this order: the types of the descriptor, the psbt and the map index, each aBTClibTypeError, a map index that is not anint(abool, or an integer of another type such as numpy’sint64) included;prv_keysand the derivation index; the descriptor’s refusal (combo(),addr()andraw(), or a hardened step without its private key); then the map-index range and the paid script. At v2026.10.29prv_keysand the derivation index came first, then the map-index range, then a hardened step without its private key, the paid script, andcombo(),addr()andraw(). Nothing checked the map index’s type: aboolor a numpy integer in range was taken as that map, and another type raised aTypeError, or aBTClibValueErrorout of range, at or just after the range check. A psbt that is not aPsbtraised anAttributeErrorat the same check.DescriptorWallet.update_psbt_inputandupdate_psbt_outputcall these functions and change the same way, after their own position check. Act on it if you call a descriptor’supdate_psbt_inputorupdate_psbt_output: import the function frombtclib_wallet.psbtand pass the descriptor first. Act on it if you pass a map index that is not anint: pass anint. Act on it if you catch theBTClibValueErrorof afloatmap index, or theAttributeErrorof a psbt that is not aPsbt: catchBTClibTypeError.miniscript_sizer,satisfaction_sizerandminiscript_solvermove frombtclib_wallet.descriptorstobtclib_wallet.psbt(ISS 620). Act on it if you import them: import them frombtclib_wallet.psbt.account_descriptorsmoves frombtclib_wallet.descriptorstobtclib_wallet.bip44(ISS 620). Act on it if you import it: import it frombtclib_wallet.bip44.A
{in or after a key, timelock or hash fragment changes the refusal (ISS 607). Inwsh()and in atr()leaf,parsecuts such a fragment as Core’sExprdoes, counting{as a bracket. TheBTClibValueErrorit raises is the key’s own refusal for a key fragment, such asnot a key expressionorinvalid key expression, where it wasunbalanced brackets in <fragment>()orinvalid key expression. Forolder()andafter()it isA function is needed within P2WSHinwsh()andtr() leaf is not a valid descriptor functionin atr()leaf, and for a hash fragmentinvalid <fragment>() hash: hex expected, where each wasunbalanced brackets in <fragment>(). Act on it if you match any of these refusals: match the new message.KeyGroup.keysholds the same keys (ISS 620).KeyGroupbuilds them withkey_data_from_bip32_key, the public name of the helper it called before, whose code is unchanged. Nothing to act on.
These are the wallet’s side of bip32 and descriptors leaving for a
package of their own (btclib-org/.github#1811): the next releases import
them from bip32-descriptors.
CHANGELOG.md’s own v2026.10.31 section has the rest.
v2026.10.29¶
BIP322 finds a proof inconclusive where a taproot input carries an annex (ISS 516).
assert_as_validraisesInconclusiveError,taproot annex is reserved for future extensions, andverifyreturnsFalse, where both accepted the proof as valid. BIP341 reserves the annex for future extensions. Act on it if you verify proofs whose taproot witness carries an annex.A miniscript hash refuses whitespace and anything else that is not hex (ISS 507).
sha256(),hash256(),ripemd160()andhash160()refuse whitespace and anything else that is not an even, non-zero count of hex characters, as Core’sIsHex, in a descriptor as in a miniscript, asBTClibValueErrornaming the fragment:invalid sha256() hash: hex expected. A hash with whitespace inside or around it was read without the whitespace, which changed the descriptor’s checksum. Act on it if you pass such a hash: remove the whitespace. Act on it if you match the refusal of a hash that is not hex: match the new message.CompactFilterFetcherchecks each block it downloads with btclib’sBlock.assert_valid_contextualat the block’s height (issue btclib-org/btclib#2705).scan_blocksfails withFetchErroron these blocks, which it accepted. Below the segwit height, a block with witnesses its coinbase commits to fails asblock: unexpected witness. A block with a time lock not yet reached, compared with the parent’s median time past where BIP113 binds, fails asblock: non-final transaction: <txid>. Where the block’s height carries the rule, a block whose version is too low fails asblock: invalid version (outdated): …, and one whose coinbase names another height asblock: invalid coinbase height: ….SECURITY.mdsays which checks a downloaded block passes.CompactFilterFetchersynchronizes a low-work chain with btclib’sHeadersSyncState(issue btclib-org/btclib#2706). A batch of headers the sync refuses fails the call withFetchError, which does not say which check failed: in the first download asheaders <first> to <last> are not a chain the rules allow, and in the second asheaders <first> to <last> are not the chain first served. Act on it if you match the messages of those refusals.SECURITY.mdverifies a release by this repository’s id (ISS 517). Its command passes--owner btclib-orgtogh attestation verifyand compares the certificate’ssourceRepositoryIdentifierwith the id, where it passed--repo btclib-org/btclib-wallet, whichSECURITY.mdsays refuses every release signed before a rename. Act on it if you verify releases with--repo: runSECURITY.md’s command.
CHANGELOG.md’s own v2026.10.29 section has the rest.
v2026.10.26¶
BIP352 skips a taproot input whose control block has an invalid length (ISS 556).
pub_key_from_inputreturnsNonefor a script-path spend whose control block is not 33 bytes plus a multiple of 32, up to 128 of them, where it returned the input’s output key. BIP341 allows no other length, and bitcoin/bips#2339 has BIP352’s reference implementation skip it.The release’s attestation names its signer workflow at a commit (issue btclib-org/.github#1870).
release.ymlcallsreusable-build.ymlofbtclib-org/.githubat a tagged commit, where it called it atrefs/heads/main. Act on it if you verify a release with--signer-workflownamingreusable-build.yml@refs/heads/main: name the workflow without a ref, asSECURITY.mddoes.
CHANGELOG.md’s own v2026.10.26 section has the rest.
v2026.10.25¶
btclib-wallet requires
ecc, the renamedbtclib-ecc(ISS 466, ISS 477). It requiresbtclib>=2026.10.24andecc>=2026.10.23, and no longer installsbtclib-ecc. The exceptions of the curve package areEccException,EccTypeError,EccValueErrorandEccRuntimeErrorofecc.exceptions, where they were theBTClibEcc*ones ofbtclib_ecc.exceptions, with no alias. Act on it if you catch one that this package lets through, as BIP322 verification does for a legacy signature whose recovered key is the point at infinity: catch the new name. Act on it if you importbtclib_eccand relied on this package to install it: install and importecc. Act on it if you setBTCLIB_ECC_NO_LIBSECP256K1to turn the libsecp256k1 bindings off: onlyECC_NO_LIBSECP256K1does.btclib-wallet requires
bip39-slip39and raises its exceptions (issue btclib-org/bip39-slip39#106). It no longer installsbtclib-mnemonics, whichbip39-slip39replaces. The mnemonic functions raiseBip39Slip39ValueErrorandBip39Slip39TypeError, which share the base classBip39Slip39Exception, where they raisedBTClibMnemonicsValueErrorandBTClibMnemonicsTypeError, underBTClibMnemonicsException. Act on it if you catch any of them: catch the new names. Act on it if you importbtclib_mnemonicsand relied on this package to install it: install and importbip39_slip39.extract_txrefuses a fee abovemax_fee_rate(ISS 459). The default isDEFAULT_MAX_FEE_RATE, Core’s-maxfeerateof 0.10 BTC per kvB, priced on the final virtual size. A missing utxo now raises even withverify_scripts=False, because the check needs every input’s amount. Act on it if you extract a psbt with a higher fee: pass a highermax_fee_rate, orNoneto skip the check.PsbtOut.script_pub_keyisNonewhere the output has no script (PR 483). It isb""wherePSBT_OUT_SCRIPTis present and empty, which a v2 psbt now keeps through serialization. Its JSON form isnullfor an absent script. The constructor’s default isNone, where it wasb"". Act on it if you read the field or its JSON, or clear a v2 script: handleNone, and assignNoneto clear one.BIP322
assert_as_validrefuses more (ISS 502, ISS 493). It refuses a proof whose sigop cost, withto_spend’s, is overMAX_BLOCK_SIGOPS_COST;OP_CODESEPARATORin a P2WSH script or a tapscript leaf; a psbt whose signed message is not the one verified; and an additional legacy input with no Non-Witness UTXO. Act on it if you verify such proofs: they were accepted, and Core or BIP322 refuses them.CompactFilterFetcherdownloads a chain that lacks the minimum work twice (ISS 354), as Core’s headers presync does, so memory is bounded before its work is known. A first synchronization from the genesis block downloads the headers twice.SECURITY.mdsays what it checks.strip_checksumquotes no checksum (ISS 478). A wrong checksum is “invalid descriptor checksum”. Act on it if you match: <checksum> expected: match the new message, and calladd_checksumfor the right checksum.Some descriptor refusals change their message (ISS 437, 438, 475, 476).
parsereads the keys of a multisig before the structure around it, and names Core’s fault for a refusedolder()orafter()number, for amulti()in tapscript and for amulti_a()in P2WSH. The same inputs are refused; only the messages change. Act on it if you match the text of a refusal: match the new one.A taproot input without
PSBT_IN_SIGHASH_TYPEacceptsSIGHASH_ALL(ISS 461), andfinalizebuilds the witness of amulti_aleaf (ISS 462).New:
EsploraFetcher.get_balance, withBalanceandBalanceReader(ISS 458), andElectrumFetcher.get_block_headers(ISS 330).
CHANGELOG.md’s own v2026.10.25 section has the rest.
v2026.10.18¶
parseandmultipath_descriptorsrefuse a key with a space before or after it (ISS 443), as Bitcoin Core does: “Key is invalid due to whitespace”. Act on it if you pass a descriptor with a space by a key: remove the space.multipath_descriptorsreads a descriptor asparsedoes (ISS 393, ISS 370, ISS 448, ISS 450, ISS 451). It hands every expansion toparse, so it refuses a descriptor whose expansionparserefuses, where it returned the expansion, and it parses a descriptor with no multipath step, where it returned it unread. It takes an optionalnetwork; with none, the network of a key is not checked. Where a descriptor has several faults,parseandmultipath_descriptorsreport the one Bitcoin Core reads first, amusig()participant’s fingerprint and origin faults carry themusig():prefix in both, andparsegives Core’s message for amusig()with a step in both its participants and its path. Act on it if you match the text of a refusal: match the new one. Act on it if you expanded a descriptorparserefuses: write it as Core reads it.CompactFilterFetcherfinds the blocks that touch a wallet’s scripts over p2p (ISS 329): it reads the BIP157/158 filters one peer serves and downloads only the blocks whose filter matches.
CHANGELOG.md’s own v2026.10.18 section has the rest.
v2026.10.16¶
btclib-wallet 2026.9.30 to 2026.10.9 fail at import beside btclib-ecc 2026.10.16 (issue btclib-org/.github#1742).
import btclib_wallet.bip32raisesImportError, and so does importingpsbt,descriptorsorwallet: btclib-ecc 2026.10.16 renamespoint_from_octetstopoint_from_octets_var, with no alias. Upgrade to this release, or keep btclib-ecc below 2026.10.16.silent_payments.output_keysreturns the keys in the order of the addresses (ISS 415). Through 2026.10.9 it grouped them by scan key, so for[A1, B, A2], A1 and A2 sharing a scan key, key 1 was A2’s and key 2 was B’s. A transaction that paired keyiwith addressipaid B’s amount to A2 and A2’s amount to B. Upgrade. Act on it if you reordered the keys yourself: stop reordering them.
Breaking changes¶
btclib-wallet requires btclib 2026.10.16 and btclib-ecc 2026.10.16 (issue btclib-org/.github#1742). Act on it if you pin either lower. Their own release notes list what else they change.
block_header_from_rawtakes a required, keyword-onlynetwork(ISS 328). It checks the proof of work against that network’s limit, where it used mainnet’s for every network. So the Electrum, Esplora, Bitcoin Core and Core REST fetchers read regtest and signet headers. Act on it if you call it: pass the network’s name.ElectrumFetcher.assert_networkraisesBTClibValueErrorfor a server of another chain (ISS 341). A mainnet fetcher over a regtest server raisedFetchError, whichFallbackFetcherfalls through. Act on it if you catchFetchErrorthere: catchBTClibValueError.psbt.combinekeeps the first psbt’s value for a key that several psbts hold (ISS 325), as Bitcoin Core does. It kept the last one’s. Act on it if a later psbt was meant to win: put it first.A psbt is refused for a BIP32 derivation key Bitcoin Core refuses (ISS 342, ISS 356, ISS 377). In the global map the key is a 78-byte xpub whose public key is a point. In an input or output map it is a 33- or 65-byte public key that is a point. Parsing, validating and serializing refuse any other. Act on it if you build such a psbt: put the key BIP174 names there.
psbt_utils.deserialize_maptakes a requiredwhich(ISS 351): the map’s name,global,inputoroutput, for its refusal. Act on it if you call it: pass the name.multipath_descriptorsrefuses what Bitcoin Core refuses (ISS 299, ISS 301, ISS 353, ISS 365, ISS 367, ISS 397). It expanded these, and refuses them: a key origin fingerprint that is not 8 hex digits; a step with a repeated value, as<1;1>; a path element that is no index; a key with a[and no], or more than one]; amusig()outsidetr()andrawtr(); amusig()with a path and a ranged participant; a hardened item of a step in amusig()path; a multipath step in the argument of a function that takes no key, asolder(<1;2>).parserefused each expansion, except those of the repeated value and ofolder(<1;2>), and the unhardened ones of a hardenedmusig()step. Act on it if you hold such a descriptor: write it as Core reads it.DescriptorWalletrefuses two branches that share a script (ISS 411, ISS 414), however their descriptors are spelled: a key origin added, a child xpub for a derivation step, or a fixed chain that is an index of a ranged one.position_ofanswered the first branch for both. The constructor derives every chain at index 0, so a chain it cannot derive, such as a hardened step with noprv_keys, is refused there. Act on it if you built such a wallet: give each branch its own chain, and the private keys a hardened step needs.Descriptor.index_ofandRangedWallet.position_ofrefuse alast_indexthat is not a non-negative integer (ISS 407, ISS 413): a negative one withBTClibValueError, where they answeredNone, and astr,None,bytes,floatorboolwithBTClibTypeError.KeyExpression.secrefuses an index that is not an int from 0 to 2**31 - 1, asDescriptordoes, a fixed key’s included, and so doMiniscript.scriptandMiniscript.satisfythrough it (ISS 383, ISS 404). Act on it if you pass another: pass an int in range.hwilooks a bare executable name up in the absolute directories of the PATH alone (ISS 416, ISS 422). An empty or relative PATH entry is skipped, and on Windows the current directory is not searched and a bare name with no period is looked for as<name>.exeonly. A name with a directory part is checked as the file it names. Act on it ifhwiwas found another way: put its directory on the PATH as an absolute path, or pass the absolute path.The messages of some refusals change, and print no key bytes (ISS 351, ISS 388, ISS 299, ISS 367, ISS 370, ISS 358, ISS 374): a duplicated psbt map key, the MuSig2 and silent-payment key checks, a partial signature,
bip85.mnemonic_from_root_key’swordsandlang, an extended key whose public key is not a point, a multipath step glued to a key, and the Esplora and Core fee estimate replies.parserefuses a multipath step in amusig()path asmultipath key expression: use multipath_descriptors first.parseandmultipath_descriptorsreport the fault Bitcoin Core reads first in a descriptor with more than one. A refused partial signature or MuSig2 key chains no__cause__, andbip85.mnemonic_from_root_keyrefuses awordsthat is not an int withBTClibTypeError, where it raisedBTClibValueError. Act on it if you match the old text: match the new one. Act on it if you catchBTClibValueErrorforwords: catchBTClibTypeErrortoo.
New¶
btclib_wallet.dlcbuilds, signs and verifies Discreet Log Contracts (ISS 331, ISS 332): the funding, execution and refund transactions of dlcspecs, their adaptor signatures, and the oracle announcements and attestations.
CHANGELOG.md’s own v2026.10.16 section has the rest.
v2026.10.9¶
A refused import, a password in an Esplora URL, a key that is not a point, a mistyped extended key and a BIP38 password are no longer quoted (GHSA-8qrf-j8jh-cx23). Releases 2026.9.24 to 2026.10.8 can put a private key, a hash of one or a password in an exception, the Esplora URL from 2026.9.30 (PR 311). Upgrade, and treat a key or password that such an error may have logged or shown as exposed.
The messages of those refusals changed.
core_import.assert_importedraisesimport refused for request {position}: error code {code}.EsploraFetcherrefuses any@inbase_url, and an invalid port asinvalid base_url port. A key that is not a point is refused with its prefix byte only, and a bad checksum or a non-ASCII character in an extended key with fixed text.bip38refuses a password that is not UTF-8 withBTClibValueErrorinstead ofUnicodeEncodeError. An out-of-range derivation index and a master fingerprint of the wrong length are refused without their value. A caller that matches on the old messages, or catchesUnicodeEncodeErrorfrombip38, has to change.The btclib floor is 2026.10.8 (ISS 306). Through 2026.10.7, btclib quotes a refused network name whole, so
KeyWallet(network=wif)put the WIF in the error (GHSA-c6h8-5hv5-3gv7).Descriptor.expand(index, prv_keys)is new. It returns the scripts and the provider atindex, whatscript_pub_keysandproviderreturn, from one derivation of each key, as Bitcoin Core’sDescriptor::Expanddoes. A caller that needs both can call it instead of the two, and derive every key once rather than twice (ISS 303).providercalled alone also derives each key once now. Nothing is removed or changed in what the existing methods return.
CHANGELOG.md’s own v2026.10.9 section has the rest.
v2026.10.8¶
A refused multipath step in a key origin is no longer quoted. In v2026.10.7, a step such as
[deadbeef/<WIF;1>]was put in the error message ofdescriptors.parseanddescriptors.multipath_descriptors, so a private key (WIF) in it was echoed. This release leaves the step out (PR 285). Upgrade if you parse descriptors that may hold a private key and log or show the errors. Treat a key in such an error from 2026.10.7 as exposed (GHSA-62jf-v327-86h5, published after this release).multipath_descriptorsandparserefuse a multipath step that is not a whole path element.<0;1>h,<0;1>',0<0;1>,<0;1>>and<<0;1>, in a key path or a key origin, raiseBTClibValueError“Key path value is not a valid uint32” (ISS 280). Bitcoin Core refuses each, with that message except<0;1>>and<<0;1>in a key origin, which it refuses as a multipath step. v2026.10.7’smultipath_descriptorsexpanded them, except<0;1>>and<<0;1>in a key origin, which it refused as Core does. Write a hardened step as<0h;1h>. A caller that matches on the message of another step in a key origin finds the step gone from it: the message is “Key path value specifies multipath in a section where multipath is not allowed”.
CHANGELOG.md’s own v2026.10.8 section has the rest.
v2026.10.7¶
btclib-wallet requires btclib 2026.10.5, which fixes GHSA-9r97-9x22-2pp4 and GHSA-rw95-w37r-537w: verifying a taproot input took time linear in the transaction’s inputs, and each legacy or segwit v0 signature check computed its hash from scratch.
bip322.verifyruns that verification on a signature it was given. Upgrading btclib-wallet installs it.request_signaturesrefuses to send a psbt asking for a sig_hash type other than SIGHASH_ALL or SIGHASH_DEFAULT. It raises on an input asking for SIGHASH_NONE, SINGLE or ANYONECANPAY, before the signer is called; pass the types you accept asallowed_sig_hash_types.SoftwareSignerapplies its own allow-list, so to sign such a psbt with it, call itssign_psbtdirectly withallowed_sig_hash_types.musig2.partial_signandfrost.partial_signrefuse an input without itsnon_witness_utxo, unless every input is taproot and none asks for ANYONECANPAY (GHSA-v4gq-j2v2-c4jp). Give each input the transaction it spends as itsnon_witness_utxo. Passrequire_non_witness_utxo=Falseonly where you know everywitness_utxoamount is right.A psbt updated from a descriptor carries a derivation for every key, as Bitcoin Core’s does. A key the descriptor gives no origin has an entry under its own fingerprint, so
hd_key_pathsandtaproot_hd_key_pathsare not empty for such a descriptor.HwiSigner.sign_psbtrefuses a psbt asking for a sig_hash type other than SIGHASH_ALL or SIGHASH_DEFAULT. It raises beforehwiruns; pass the types you accept as its keyword-onlyallowed_sig_hash_types.request_signaturesdoes not pass its allow-list on, so to send such a psbt to a device, callsign_psbtdirectly and hold its answer withassert_signatures_only(psbt, answer)beforecombine.A
ScriptWalletpsbt carries a derivation for every key, as a descriptor’s does. A key of aKeyGroupgiven no origin has an entry under its own fingerprint, sohd_key_pathsis not empty for such a group. Of two explicit origins for one key, the first is written, not the last.The attestation bundle is attached as
v<version>.intoto.jsonlfrom v2026.10.4 on, where earlier releases attachv<version>.attestation.jsonl. A script that downloads it by name, or passes it togh attestation verify --bundle, uses the new name.sign,request_signaturesandHwiSigner.sign_psbtraise on an input asking for SIGHASH_SINGLE with no output at its index, whateverallowed_sig_hash_typessays. Such a signature commits to no output, so whoever holds it can spend the input to any output. Give the input an output at its index, or ask for another type.finalizestill checks a signature of this kind.A regtest silent payment address starts with
sprt1, as Bitcoin Core’s regtest requires, where earlier releases givetsp1.keys_from_addressreads both, with the network type"test". Make a stored regtesttsp1address again withaddress_from_keys(..., "regtest"), and update anytsp1string a test compares against.Bolt11Invoice.from_invoicerefuses malformed or repeated fields. Ap,s,hornof the wrong length, a secondp,s,d,horn, anx,cor9starting with a zero word, and an amount with a leading zero raiseBTClibValueError, where earlier releases skipped a wrong-length field, read the first of a repeated one, or read an amount without its leading zeros. This includes an invoice that an earliersignwrote withexpiry=0ormin_final_cltv_expiry=0: sign it again.A psbt keeps an explicit
sig_hash_typeof 0 throughserializeandcombine.signrefuses an ECDSA input asking for it after a round trip through bytes too, where it signed SIGHASH_ALL.HwiSigner.sign_psbtandrequest_signaturesrefuse SIGHASH_DEFAULT on an input not known to be taproot, where a device signed SIGHASH_ALL. To sign such a psbt, ask its creator for SIGHASH_ALL or remove the field.silent_payments.output_keysrefuses an address of another network than itsnetworkargument,"mainnet"by default, as Bitcoin Core’s decoder does. Ansprt,tsporspaddress that is not that network’s raisesBTClibValueError, so a caller paying testnet, signet or regtest passes thenetworktoo.wallet_policy_descriptor,wallet_policy_addressandwallet_policyrefuse a template BIP388 does not allow. A top-levelmulti()orsortedmulti(), and apk()insidesh(), raiseBTClibValueError; so do a top-levelpk(),combo()orrawtr()in the first two, where earlier releases gave a descriptor or an address. Read such a descriptor withdescriptors.parse.
CHANGELOG.md’s own v2026.10.7 section has the rest.
v2026.10.4¶
Signing refuses a sig_hash type other than SIGHASH_ALL or SIGHASH_DEFAULT unless the caller allows it (GHSA-qq38-77mp-j6wr).
sign,SoftwareSigner.sign_psbt,musig2.partial_signandfrost.partial_signraise on an input asking for SIGHASH_NONE, SINGLE or ANYONECANPAY; pass the types you accept asallowed_sig_hash_types.request_signaturespasses none, so callSoftwareSigner.sign_psbtdirectly to sign such a psbt. A legacy SIGHASH_SINGLE input with no output at its index is refused whatever is allowed, andecdsa_sig_hashandPsbtView.ecdsa_sig_hashrefuse it too.finalize,assert_signedandassert_signatures_onlyrefuse an ECDSA signature other than SIGHASH_ALL on an input withoutPSBT_IN_SIGHASH_TYPE; set the field on a psbt whose signatures use another type.sign,SoftwareSigner.sign_psbtandPsbt.assert_signablerefuse an input without itsnon_witness_utxo, unless every input is taproot and none asks for ANYONECANPAY (GHSA-v4gq-j2v2-c4jp). Give each input the transaction it spends as itsnon_witness_utxo. Passrequire_non_witness_utxo=Falseonly where you know everywitness_utxoamount is right: a wrong one can be spent as fee.btclib-wallet requires btclib 2026.10.4, btclib-ecc 2026.10.2 and btclib-secp256k1 0.8.0.10. btclib 2026.10.4 fixes GHSA-9fr5-46w5-5f9r, which made
bip322.verifyrun for minutes on a crafted signature; 0.8.0.10 fixes GHSA-8h6f-34jj-7p6c, an invalid-curve oracle insilentpayments.scan_outputs. Upgrading btclib-wallet installs btclib and btclib-ecc; thesecp256k1extra installs the bindings.Verifying a release’s attestation names a new signer and the tag.
gh attestation verifytakes--signer-workflow btclib-org/.github/.github/workflows/reusable-build.yml@refs/heads/mainand--source-ref refs/tags/v<version>; SECURITY.md has the command. Earlier releases keepreusable-attest.yml.descriptors.parserefuses a key of another network. A WIF or an extended key whose prefix is not thenetwork’s raisesBTClibValueErrorthere, where the WIF was accepted and the extended key was refused only byscript_pub_keys(). A caller that parses a descriptor for a network its keys are not of has to pass the rightnetwork.bip39.mxprv_from_mnemonicandelectrum.mxprv_from_mnemonicrefuse a falsy passphrase of another type. An emptybytes,0,Falseor[]derived the wallet without a passphrase; passNoneor""for that.A miniscript repeating a public key is refused under different spellings of it.
descriptors.parsedoes so as Bitcoin Core does, except for a key with a hardened step.A malleable miniscript keeps neither “s”, “f” nor “e”.
Miniscript.propertiesdrops them, andis_signature_requiredis false for it.joinempties the signatures of a version 0 psbt, andsignupdates a version 2 psbt’s modifiable flags. Sign the joined psbt again.joinrefuses a version 2 psbt signed with anything but SIGHASH_NONE|ANYONECANPAY.extract_txverifies by default. It runs every input’s scripts and checks that the outputs do not exceed the inputs, so it raises on a psbt it extracted before: one with a bad signature, a missing utxo or outputs above the inputs. Passverify_scripts=Falseto extract without the check.joinrefuses to change the lock time or the tx version of a signed version 2 psbt. The signatures would stop verifying. Join the psbts before they are signed, or give them the same lock time and tx version.Miniscript.has_duplicate_keys,is_sane,is_sane_subexpressionandinsane_subare methods. Call them with parentheses; without them,if node.is_sane:is always true, and mypy reports it astruthy-function. Passprv_keys, the mappingparsefills, to derive a hardened step:descriptors.parserefuseswsh(or_i(pk(XPRV/1h),pk(<the key it derives>))). Without its private key, a key with a hardened step is still compared as written.descriptors.parserefuses a threshold no script can meet. Amulti()orsortedmulti()threshold of zero or above its key count, and amulti_a()orsortedmulti_a()one of zero, above its key count, or of more than 999 keys, raiseBTClibValueError, where they were stored. Athresh()of more than 1000 arguments is refused too, a limit of this library.A number of over 4300 digits is a
BTClibValueError. A derivation index, a threshold, anolder()orafter()number and a@Nof that size raised the built-inValueError; they are refused at ten digits now.Bolt11Invoice.from_invoicerefuses an amount of more than 20 digits, which its amount parser read up to 4300 digits.A
prv_keysthat is not a mapping raisesBTClibTypeError. The descriptor,KeyExpression,MiniscriptandDescriptorWalletmethods taking it, anddescriptors.normalized, check it asparsedoes, where a string raisedAttributeError.SilentPaymentOutput’sreprleaves outprv_key_tweak. The tweak is a secret; read the field, not therepr, where you need it.
CHANGELOG.md’s own v2026.10.4 section has the rest.
v2026.9.30¶
A binary-string entropy passed as bytes is refused with a
BTClibTypeError by mnemonic.entropy’s functions taking one, which
read it as the digits it spells; pass the str instead. A mnemonic that
is not a str is refused with a BTClibTypeError rather than a bare
TypeError or AttributeError.
mnemonic.slip39.master_secret_from_mnemonics and mxprv_from_mnemonics
refuse shares passed as an iterable that is not a sequence – a set, a
generator, an iterator, dict.keys() – with a BTClibTypeError, where
they read it; pass a list or a tuple instead.
mnemonic.slip39.mnemonics_from_master_secret refuses with a
BTClibTypeError a groups passed as a set or a dict, and a bool as a
threshold, a member count or the iteration exponent, where it read them;
pass a list or a tuple of integer pairs, and integers.
mnemonic.entropy.bin_str_entropy_from_rolls refuses the same way rolls
passed as a set or a generator and a bool as a roll or as bits.
mnemonic.slip39.Share refuses with a BTClibTypeError a value that is
not bytes – a bytearray or a list of ints included – and a bool as
an integer field or a non-bool as extendable, where it held them; pass
bytes, integers and a bool. mxprv_from_mnemonics refuses a falsy
passphrase of another type, 0, [] or b"", where it read the empty
passphrase; pass None or "". mnemonics_from_master_secret refuses
an entropy_source answering anything but bytes or a bytearray of
the length asked – a 1-of-1 backup read a list, a memoryview or a
draw of another length; return exactly that.
fetch.BitcoinCoreFetcher and fetch.BitcoinCoreRestFetcher refuse with a
BTClibTypeError a client that is not a BitcoinCoreRpcClient or a
BitcoinCoreRestClient respectively, where a stand-in answering the
methods they call worked; pass an instance of that class or a subclass.
fetch.ElectrumFetcher refuses a timeout that is no number, a bool,
not positive, or above threading.TIMEOUT_MAX, which it handed as given
to a transport of the caller’s; pass a positive number of seconds. fetch.EsploraFetcher
refuses a base_url carrying a user or a password, or without a host,
which a transport of the caller’s received; pass the url without them,
and let that transport add the credentials.
tx_builder.build_psbt, coin_selection.select_coins, knapsack and
single_random_draw require change_script_pub_key: a call that left it
out, and so sent every leftover satoshi to the fee, raises a TypeError;
pass the change script, or None for a sweep.
tx_builder.build_psbt refuses with a BTClibValueError a fee above
max_fee, 0.10 BTC unless raised, and an output being paid below its
dust threshold. It refuses a non-zero lock_time too when every input’s
sequence is final: set a non-final PsbtIn.sequence, such as
0xfffffffe, on an input for the lock time to bind.
psbt.sign refuses with a BTClibValueError a psbt paying a silent payment
it used to sign: one whose silent payment output has no script yet – run
psbt.silent_payments.set_input_share or set_global_share, then
set_output_scripts, before signing – one with an input’s sighash other
than SIGHASH_ALL, and one whose shares, scripts or modifiable flags
psbt.silent_payments.assert_as_valid refuses. psbt.extract_tx refuses
what that function refuses, and a silent payment output with no script;
check_validity=False extracts as before. psbt.combine refuses two psbts
carrying different scripts for one silent payment output.
tx_builder.build_psbt also refuses with a BTClibValueError a fee above
what max_fee_rate, 0.10 BTC/kvB unless raised, asks of the estimated
virtual size, however far below max_fee it is; pass a higher
max_fee_rate where such a fee is meant.
A psbt with an input whose witness_utxo is not, in amount and script,
the output of its non_witness_utxo the outpoint names is refused with a
BTClibValueError by Psbt.assert_valid, and so by Psbt.parse and
every function validating the psbt, where it was accepted and the
witness_utxo read; set it to that output, or drop it.
bip322.assert_as_valid refuses a proof of funds in which it contradicts
the transaction an earlier input carries.
psbt.estimated_input_sizes refuses with a BTClibValueError a
psbt_in whose non_witness_utxo is not the transaction the tx_in’s
outpoint names, and one whose witness_utxo differs from the output that
outpoint names, where it answered an estimate; pass the
TxIn the input is spent by, and a witness_utxo equal to that output.
psbt_signer.request_signatures refuses a psbt paying a silent payment that
psbt.sign would refuse, before the signer is asked, where it sent it on.
psbt.silent_payments counts an input by the script it spends, and refuses
with a BTClibValueError a counted input whose key the psbt does not carry
where it left the input out: give every p2wpkh, p2pkh and p2sh-p2wpkh input
a PSBT_IN_BIP32_DERIVATION whose key the script commits to, and a p2sh
input its redeem script. A taproot input whose internal key is BIP341’s NUMS
point is counted unless PSBT_IN_TAP_MERKLE_ROOT or a control block proves
it. set_output_scripts refuses until every counted input has a share, where
it derived the scripts from the shares there were.
hwi.HwiSigner.sign_psbt called directly refuses such a psbt the same way,
before hwi runs, where it sent it to the device; and it refuses a request
that is no Psbt with a BTClibTypeError rather than an AttributeError.
psbt.combine refuses with a BTClibValueError psbts whose merge
Psbt.assert_valid refuses, where it returned that psbt; drop from the
copies the field that contradicts the others – a witness_utxo differing
from another copy’s non_witness_utxo output – before combining.
It refuses with a BTClibTypeError a psbts that is not a sequence – a
generator, an iterator – where it read it; pass a list or a tuple.
psbt.join refuses with a BTClibTypeError a psbts that is not a
sequence – a dict view, any container that is only iterable – where it
joined it; pass a list or a tuple.
descriptors.KeyExpression refuses with a BTClibValueError an extended
private key as xkey, where it held it; pass its xpub, and the xprv under
that xpub in prv_keys where a hardened step needs it.
descriptors.KeyExpression’s xkey holds an extended public key of a
version btclib decodes, a wallet-policy placeholder wallet_policy writes
– @N, @N/**, @N/<M;N>/*, musig(@N,...) with one of those suffixes,
K – or nothing. Any other str is refused with a BTClibValueError and
any other type with a BTClibTypeError, where they were held; pass an xpub.
silent_payments.keys_from_address refuses with a BTClibValueError a
mixed-case address and one holding a character outside ASCII, where it read
the address the string lowers to; pass the address all lower case or all
upper case. For such a spelling of an address a wallet handed out,
address in wallet answers False and Wallet.address_info raises, where
both found the address.
silent_payments.keys_from_address and silent_payments.output_keys,
which reads each address through it, BIP32KeyData.b58decode and what
reads an extended key through it, bip32.derive among them,
bip322.Sig.b64decode, bip322.verify and assert_as_valid for the
signature, Psbt.b64decode, tx_or_psbt.tx_or_psbt_from_any,
BIP32KeyOrigin.from_description and bip32.str_from_der_path’s
fingerprint strip only space, tab, newline, carriage return, vertical tab
and form feed. Text padded with U+00A0, U+3000, U+2028, U+0085 or another
character outside ASCII that str.isspace counts is refused with a
BTClibValueError, where it was read as the value it wraps, and so is
text padded with U+001C to U+001F. For such a spelling of an address a
wallet handed out, address in wallet answers False and
Wallet.address_info raises. Strip that padding before passing the text.
mnemonic.entropy.bin_str_entropy_from_int refuses with a
BTClibValueError a string entropy that is not ASCII digits – binary after
0b, hex after 0x, decimal otherwise – once space, tab, newline,
carriage return, vertical tab and form feed are stripped around it, where
int read 0x1_0, 1_6, +16 and fullwidth or Arabic-Indic digits as 16
and U+00A0 or U+3000 was stripped too. The functions reading a binary-string
entropy, bin_str_entropy_from_str, bytes_entropy_from_str and
bin_str_entropy_from_entropy among them, refuse one holding anything but
ASCII 0 and 1 – a sign, 0b, whitespace, an underscore – which int
read as binary; bytes_entropy_from_str raised a bare OverflowError on a
leading -. Pass ASCII digits alone. The refusals read invalid entropy: what follows 0x is not ASCII hex digits and invalid entropy: not ASCII decimal digits, where they said not a base 16 number and not a base 10 number, and a negative entropy’s reads negative entropy, without the
number. bin_str_entropy_from_wordlist_indexes and
bin_str_entropy_from_rolls name the range and not the value of an index or
a roll outside it: invalid index: not in [0, 2048), invalid roll: not in [1-6]. Match invalid entropy, negative entropy, invalid index and
invalid roll alone.
descriptors.parse refuses with a BTClibValueError a bare multi() or
sortedmulti() of more than three keys, one inside sh() whose redeem script
is over 520 bytes – sixteen compressed keys are 547 – and one of more than
twenty keys anywhere, where it parsed them; put the keys of the first two
inside wsh() or sh(wsh()) instead. wallet_policy_descriptor refuses the
same, the descriptor it builds being read by parse.
Psbt.b64decode refuses with a BTClibValueError text holding a
character outside the base64 alphabet – a line break, a space, U+001C,
! – anywhere past the ASCII whitespace it strips from either end,
where it decoded the psbt the rest of the text spells. Remove the line
breaks from a wrapped psbt, or pass it to
tx_or_psbt.tx_or_psbt_from_any, which removes them.
bip32.indexes_from_der_path, hardenings_from_der_path,
int_from_index_str and every function reading a path string through
them, bip32.derive and BIP32KeyOrigin.from_description among them,
refuse with a BTClibValueError a step whose number is not ASCII decimal
digits – 1_0, +1, -0, fullwidth or Arabic-Indic digits – or that is
padded with anything but space, tab, newline, carriage return, vertical tab
and form feed, where it was read as the number. With bip380_enforced=True
they refuse a step padded at all, and so descriptors.parse refuses a
step with a space around it. BIP32KeyOrigin.from_description refuses text
whose ninth character is not /, where it dropped that character and read
deadbeef0/1 as deadbeef/1. int_from_index_str refuses a step that is
not a str with a BTClibTypeError, and reads a step with ASCII whitespace
after its symbol, "0h ", which it refused. Pass each step as ASCII digits.
The refusals read invalid derivation index: not ASCII decimal digits and
invalid index: not below 2**31, where they quoted the step or its number;
match those. bip85’s functions write their index into a path string, and
refuse a negative one with the first and one of 2**31 or more with the
second.
descriptors.parse and miniscript.parse refuse with a BTClibValueError
a / followed by no path step, in a key origin, after an extended key or
after a musig() – [deadbeef/], xpub.../, xpub...//*,
musig(...)/ – where they read the key expression as though that /
were absent. Remove the /; the refusal reads invalid derivation index.
BIP32KeyOrigin.from_description, whose reading of a path is the lenient
one, reads deadbeef/ as deadbeef.
Psbt.b64decode, bip322.Sig.b64decode, and bip322.verify and
assert_as_valid for the signature, refuse with a BTClibValueError
base64 that is not the text base64.b64encode writes for its bytes, where
they read those bytes: a bit set in what the last character leaves over,
YR== read as YQ==, and on CPython and PyPy 3.11 an = after a whole
group. The refusal reads invalid base64 encoding: not canonical, and
bip322.verify raises it for a legacy signature so encoded, where it
answered False. tx_or_psbt.tx_or_psbt_from_any refuses such a str as
neither hex nor base64, and reads such bytes as a raw transaction, where
both were read as the psbt. Pass the text base64.b64encode writes, which
is the text Bitcoin Core writes and the only text it reads.
A refusal in mnemonic no longer quotes secret material, so its text
changed: an unknown word reads unknown '<lang>' word at position <n>,
where it was unknown '<lang>' word: '<word>', and a SLIP-0039 one
not in the SLIP-0039 word-list: words at positions [<n>, ...]. A BIP39
checksum reads invalid checksum: <n> words, a SLIP-0039 padding
invalid padding: must be all zeros, and an unrecognized Electrum
sentence unknown electrum mnemonic version; not in [...]. Match the
new text if you match these. mnemonic.mnemonic_from_indexes refuses an
index outside the word-list, a negative one included, which read from
the end of the list; pass indexes in [0, len(wordlist)).
WordLists.langs_of_words refuses a lone str, which it read one
character at a time; pass the list of words.
mnemonic.mnemonic_from_indexes and WordLists.langs_of_words refuse
with a BTClibTypeError an iterable that is not a sequence – a
generator, a set, an iterator – where they read it; pass a list or a
tuple. mnemonic_from_indexes refuses too an index that is a bool or
an integer of a type other than int, numpy.int64 or an object with
__index__ included, where it read it; pass ints.
dispatch.seed_type_from_mnemonic and all_seed_types_from_mnemonic
refuse a lang that is not a str with a BTClibTypeError, where they
answered "" and []; pass the language code.
The BIP39, SLIP39 and Electrum mnemonic schemes are
btclib-mnemonics’, a
dependency of this package, and btclib_wallet.mnemonic keeps what
builds a key from their seed: bip39.mxprv_from_mnemonic,
slip39.mxprv_from_mnemonics, electrum.mxprv_from_mnemonic and
electrum.old_master_pub_key_from_mnemonic. Every path below stops
resolving, and nothing re-exports it; import the name from
btclib_mnemonics instead. A refusal those four functions pass on from
btclib_mnemonics, of a mnemonic, a share or a passphrase, is that
package’s own BTClibMnemonicsTypeError or BTClibMnemonicsValueError,
a TypeError or a ValueError and no BTClibException, where it was a
BTClibTypeError or a BTClibValueError; catch TypeError and
ValueError. electrum.mxprv_from_mnemonic still refuses a 2fa, a
2fa_segwit or an old mnemonic with its own BTClibValueError, and for
an old one that refusal now ends use old_master_pub_key_from_mnemonic,
where it named old_master_prv_key_from_mnemonic. The paragraphs above
that name a function that moved describe it as it is under
btclib_mnemonics, where each BTClibTypeError or BTClibValueError
they name for it is a BTClibMnemonicsTypeError or a
BTClibMnemonicsValueError, and where the entropy conversions they name
are private.
btclib_wallet.mnemonic.dispatchisbtclib_mnemonics.dispatch.btclib_wallet.mnemonic.entropyisbtclib_mnemonics.entropy, less the functions the bullets below make private.btclib_wallet.mnemonic.mnemonicisbtclib_mnemonics.mnemonic.btclib_wallet.mnemonic’sBinStrisbtclib_mnemonics.entropy.BinStr.btclib_wallet.mnemonic’sEntropyisbtclib_mnemonics.entropy.Entropy.btclib_wallet.mnemonic’sbin_str_entropy_from_randomisbtclib_mnemonics.entropy.bin_str_entropy_from_random.btclib_wallet.mnemonic’sbin_str_entropy_from_rollsisbtclib_mnemonics.entropy.bin_str_entropy_from_rolls.btclib_wallet.mnemonic’scollect_rollsisbtclib_mnemonics.entropy.collect_rolls.btclib_wallet.mnemonic’sMnemonicisbtclib_mnemonics.mnemonic.Mnemonic.btclib_wallet.mnemonic’sWORDLISTSisbtclib_mnemonics.mnemonic.WORDLISTS.btclib_wallet.mnemonic’sindexes_from_mnemonicisbtclib_mnemonics.mnemonic.indexes_from_mnemonic.btclib_wallet.mnemonic’smnemonic_from_indexesisbtclib_mnemonics.mnemonic.mnemonic_from_indexes.btclib_wallet.mnemonic’snormalize_mnemonicisbtclib_mnemonics.mnemonic.normalize_mnemonic.btclib_wallet.mnemonic’sbin_str_entropy_from_bytesis gone, private inbtclib_mnemonics: pass the bytes to the scheme’smnemonic_from_entropy, which reads them.btclib_wallet.mnemonic’sbin_str_entropy_from_entropyis gone, private inbtclib_mnemonics: pass the entropy to the scheme’smnemonic_from_entropy, which reads it.btclib_wallet.mnemonic’sbin_str_entropy_from_intis gone, private inbtclib_mnemonics: pass the integer to the scheme’smnemonic_from_entropy, which reads it.btclib_wallet.mnemonic’sbin_str_entropy_from_stris gone, private inbtclib_mnemonics: pass the binary string itself.btclib_wallet.mnemonic’sbin_str_entropy_from_wordlist_indexesis gone, private inbtclib_mnemonics: usebtclib_mnemonics.mnemonic.mnemonic_from_indexesand the scheme’sentropy_from_mnemonic.btclib_wallet.mnemonic’sbytes_entropy_from_stris gone, private inbtclib_mnemonics:int(entropy, 2).to_bytes(len(entropy) // 8, "big")is the conversion.btclib_wallet.mnemonic’swordlist_indexes_from_bin_str_entropyis gone, private inbtclib_mnemonics: use the scheme’smnemonic_from_entropyandbtclib_mnemonics.mnemonic.indexes_from_mnemonic.btclib_wallet.mnemonic.bip39’sentropy_from_mnemonicisbtclib_mnemonics.bip39.entropy_from_mnemonic.btclib_wallet.mnemonic.bip39’slang_from_mnemonicisbtclib_mnemonics.bip39.lang_from_mnemonic.btclib_wallet.mnemonic.bip39’smnemonic_from_entropyisbtclib_mnemonics.bip39.mnemonic_from_entropy.btclib_wallet.mnemonic.bip39’sseed_from_mnemonicisbtclib_mnemonics.bip39.seed_from_mnemonic.btclib_wallet.mnemonic.electrum’sELECTRUM_WORDLISTSisbtclib_mnemonics.electrum.ELECTRUM_WORDLISTS.btclib_wallet.mnemonic.electrum’sentropy_from_mnemonicisbtclib_mnemonics.electrum.entropy_from_mnemonic.btclib_wallet.mnemonic.electrum’shex_seed_from_old_mnemonicisbtclib_mnemonics.electrum.hex_seed_from_old_mnemonic.btclib_wallet.mnemonic.electrum’slang_from_mnemonicisbtclib_mnemonics.electrum.lang_from_mnemonic.btclib_wallet.mnemonic.electrum’smnemonic_from_entropyisbtclib_mnemonics.electrum.mnemonic_from_entropy.btclib_wallet.mnemonic.electrum’sold_master_prv_key_from_mnemonicisbtclib_mnemonics.electrum.old_master_prv_key_from_mnemonic.btclib_wallet.mnemonic.electrum’sold_mnemonic_from_hex_seedisbtclib_mnemonics.electrum.old_mnemonic_from_hex_seed.btclib_wallet.mnemonic.electrum’sversion_from_mnemonicisbtclib_mnemonics.electrum.version_from_mnemonic.btclib_wallet.mnemonic.slip39’sShareisbtclib_mnemonics.slip39.Share.btclib_wallet.mnemonic.slip39’smaster_secret_from_mnemonicsisbtclib_mnemonics.slip39.master_secret_from_mnemonics.btclib_wallet.mnemonic.slip39’smnemonic_from_shareisbtclib_mnemonics.slip39.mnemonic_from_share.btclib_wallet.mnemonic.slip39’smnemonics_from_master_secretisbtclib_mnemonics.slip39.mnemonics_from_master_secret.btclib_wallet.mnemonic.slip39’sshare_from_mnemonicisbtclib_mnemonics.slip39.share_from_mnemonic.
The bound on a timeout that fetch.ElectrumFetcher refuses is
fetch.transport.MAX_TIMEOUT, 2147483 seconds, where the paragraph above
names threading.TIMEOUT_MAX; pass at most that many seconds.
fetch.EsploraFetcher refuses at construction, with a BTClibTypeError
or a BTClibValueError, a timeout that is no number, a bool, not
positive, or above fetch.transport.MAX_TIMEOUT, 2147483 seconds, where
its first fetch raised a FetchError and a timeout above that bound
reached a transport of the caller’s. fetch.transport.TlsLineTransport
refuses a timeout above that bound with a BTClibValueError, where it
waited with one up to what the platform’s socket took and failed past
it, with an OverflowError or, where the socket’s wait refused it, a
FetchError; its refusals read non-numeric timeout: <type> and
timeout is not a positive number of seconds up to 2147483, where they
quoted the value. Pass a positive number of seconds up to that bound.
CHANGELOG.md’s own v2026.9.30 section has the rest.
v2026.9.24¶
The first release of btclib-wallet, whose modules leave btclib
(issue btclib-org/btclib#2129). A caller importing one of them from
btclib installs this package and imports it from btclib_wallet
instead, the path below the package unchanged: btclib.bip32 becomes
btclib_wallet.bip32, btclib.mnemonic.bip39 becomes
btclib_wallet.mnemonic.bip39.
CHANGELOG.md’s own v2026.9.24 section has the rest.