taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 84976f692f0a6df7b302d69c872ac2d60b09ae2d
parent 9d4d47f4a417639d1f59b730af409d5eb1c8c561
Author: Florian Dold <dold@taler.net>
Date:   Tue, 21 Jul 2026 10:55:15 +0200

util: validate bitcoin payto addresses as segwit addresses

The address was checked against bech32 only, so taproot and every later
witness version were rejected although the exchange accepts them.

Diffstat:
Mpackages/taler-util/src/payto.ts | 14+++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/packages/taler-util/src/payto.ts b/packages/taler-util/src/payto.ts @@ -15,6 +15,7 @@ */ import { BitcoinBech32 } from "./bech32.js"; +import { BitcoinSewgit } from "./segwit_addr.js"; import { generateFakeSegwitAddress } from "./bitcoin.js"; import { Codec, Context, DecodingError, renderContext } from "./codec.js"; import { assertUnreachable } from "./errors.js"; @@ -551,7 +552,10 @@ export namespace Paytos { | { targetType: PaytoType.Bitcoin; pos: 0; - error: ResultError<BitcoinBech32.BitcoinParseError>; + error: ResultError< + | BitcoinBech32.BitcoinParseError + | BitcoinSewgit.BitcoinSewgitParseError + >; } | { targetType: PaytoType.Bitcoin; @@ -687,10 +691,10 @@ export namespace Paytos { } const address = cs[0].toLowerCase(); - const btRes = BitcoinBech32.decode( - address, - BitcoinBech32.Encodings.BECH32, - ); + // Validate as a segwit address rather than as a bare bech32 string: + // the witness version decides which checksum constant applies, so + // pinning bech32 here rejects taproot and every later version. + const btRes = BitcoinSewgit.decode(address); if (!opts.ignoreComponentError && Result.isError(btRes)) { return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, { pos: 0 as const,