Accept Taproot (bech32m) BTC addresses in address validation#453
Merged
Conversation
added 2 commits
June 8, 2026 12:20
is_valid_address validated with the bech32 package, which implements only BIP-173 bech32 (witness v0), so every Taproot address (bc1p…, witness v1 / bech32m) failed the checksum. That rejected all TAO->BTC swaps paying out to a Taproot wallet — at the CLI pre-check and validator confirm — with a misleading "Invalid destination address format" (fixes #448). Route is_valid_address and to_mainnet_address through embit (already a dependency, already used for the send path). embit validates/encodes all address types offline — no RPC — so the hand-rolled bech32/base58 logic is replaced and the direct bech32 dependency is dropped (it stays installed transitively via bitcoin-message-tool). to_mainnet_address output is verified byte-identical to the prior behavior for every type that reaches it. Diagnosis and the BIP-350-library fix direction came from the issue reporter.
entrius
approved these changes
Jun 8, 2026
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.
Fixes #448.
Problem
BitcoinProvider.is_valid_addressvalidated with thebech32package, which implements only BIP-173 bech32 (witness v0). Every Taproot address (bc1p…/tb1p…/bcrt1p…, witness v1, encoded with bech32m / BIP-350) fails that checksum, so TAO→BTC swaps paying out to a Taproot wallet were rejected 100% of the time — at the CLI pre-check (swap.py) and the validator confirm (axon_handlers.py) — with a misleading "Invalid destination address format". Taproot is a growing share of modern wallet receive addresses, so this blocked a real and growing class of legitimate swaps.The rest of the pipeline already supports Taproot (payout build via embit's
address_to_scriptpubkey; dest-verification string-matches Esplora'sscriptpubkey_address) — only the format gate was in the way.Fix
Route
is_valid_addressandto_mainnet_addressthrough embit, which is already a direct dependency and already used in this same file for the send path. embit validates/encodes all address types (legacy, segwit v0, Taproot) offline — no RPC, so:is_valid_addressnow accepts the full mainnet/testnet/regtest × P2PKH/P2SH/P2WPKH/P2WSH/P2TR matrix and still rejects malformed input (it's marginally stricter — it also validates witness-program length).to_mainnet_addressre-encodes the scriptPubKey under the mainnet network. Verified byte-identical to the prior bech32/base58 output for every type that reaches it (testnet/regtest P2PKH/P2SH/P2WPKH + mainnet passthrough).bech32dependency is dropped frompyproject.toml. It remains inuv.locktransitively viabitcoin-message-tool, so nothing else breaks.base58stays — still used byto_mainnet_wif.Scope
Targeted to the TAO→BTC payout-to-Taproot flow. Explicitly out of scope (separate, larger work; no change here):
Tests
Added
TestIsValidAddress(full valid/invalid matrix incl. an explicit Taproot regression guard) andTestToMainnetAddress(byte-identical conversion checks) totests/test_bitcoin_signing.py.uv run pytest tests/ -q→ 682 passed. Existing BIP-137 sign/verify roundtrip tests still pass (confirmsto_mainnet_address/to_mainnet_wifunaffected).grep -rn bech32 allways/→ zero references.Credit to the issue reporter for the diagnosis and the BIP-350-library fix direction.