diff --git a/packages/taler-util/src/bitcoin.test.ts b/packages/taler-util/src/bitcoin.test.ts new file mode 100644 index 000000000..287cd7e66 --- /dev/null +++ b/packages/taler-util/src/bitcoin.test.ts @@ -0,0 +1,53 @@ +/* + This file is part of GNU Taler + (C) 2018-2019 GNUnet e.V. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** + * Type-safe codecs for converting from/to JSON. + */ + +import test from "ava"; +import { + generateFakeSegwitAddress, +} from "./bitcoin.js"; + +test("generate testnet", (t) => { + const { addr1, addr2 } = generateFakeSegwitAddress("B9E0EXNDKGJX7WFAEVZCZXM0R661T66YWD71N7NRFDEWQEV10XSG", "tb1qhxrhccqexg0dv4nltgkuw4fg2ce7muplmjsn0v") + + t.assert(addr1 === "tb1qtfwqwaj6tsrhdtvuyhflr6nklm8ldqxpf0lfjw"); + t.assert(addr2 === "tb1qmfwqwa5vr5vdac6wr20ts76aewakzpmns40yuf"); +}); + +test("generate mainnet", (t) => { + const { addr1, addr2 } = generateFakeSegwitAddress("B9E0EXNDKGJX7WFAEVZCZXM0R661T66YWD71N7NRFDEWQEV10XSG", "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq") + //bc + t.assert(addr1 === "bc1qtfwqwaj6tsrhdtvuyhflr6nklm8ldqxprfy6fa"); + t.assert(addr2 === "bc1qmfwqwa5vr5vdac6wr20ts76aewakzpmn6n5h86"); +}); + +test("generate Regtest", (t) => { + const { addr1, addr2 } = generateFakeSegwitAddress("B9E0EXNDKGJX7WFAEVZCZXM0R661T66YWD71N7NRFDEWQEV10XSG", "bcrtqhxrhccqexg0dv4nltgkuw4fg2ce7muplmjsn0v") + + t.assert(addr1 === "bcrt1qtfwqwaj6tsrhdtvuyhflr6nklm8ldqxptxxy98"); + t.assert(addr2 === "bcrt1qmfwqwa5vr5vdac6wr20ts76aewakzpmnjukftq"); +}); + + +test("unknown net", (t) => { + t.throws(() => { + generateFakeSegwitAddress("B9E0EXNDKGJX7WFAEVZCZXM0R661T66YWD71N7NRFDEWQEV10XSG", "abqhxrhccqexg0dv4nltgkuw4fg2ce7muplmjsn0v") + }) + +}); diff --git a/packages/taler-util/src/bitcoin.ts b/packages/taler-util/src/bitcoin.ts index 0dd83e2db..62d8d8dce 100644 --- a/packages/taler-util/src/bitcoin.ts +++ b/packages/taler-util/src/bitcoin.ts @@ -23,7 +23,7 @@ * Imports. */ import { AmountJson, Amounts } from "./amounts.js"; -import { getRandomBytes, decodeCrock } from "./talerCrypto.js"; +import { decodeCrock } from "./talerCrypto.js"; import * as segwit from "./segwit_addr.js"; export interface SegwitAddrs { @@ -44,13 +44,14 @@ const hext2buf = (hexString: string) => export function generateFakeSegwitAddress( reservePub: string, - addr: string, + addr: string ): SegwitAddrs { const pub = decodeCrock(reservePub); - const first_rnd = getRandomBytes(4); - const second_rnd = new Uint8Array(first_rnd.length); - second_rnd.set(first_rnd); + const first_rnd = new Uint8Array(4); + first_rnd.set(pub.subarray(0, 4)) + const second_rnd = new Uint8Array(4); + second_rnd.set(pub.subarray(0, 4)); first_rnd[0] = first_rnd[0] & 0b0111_1111; second_rnd[0] = second_rnd[0] | 0b1000_0000; @@ -58,6 +59,7 @@ export function generateFakeSegwitAddress( const first_part = new Uint8Array(first_rnd.length + pub.length / 2); first_part.set(first_rnd, 0); first_part.set(pub.subarray(0, 16), 4); + const second_part = new Uint8Array(first_rnd.length + pub.length / 2); second_part.set(second_rnd, 0); second_part.set(pub.subarray(16), 4); diff --git a/packages/taler-util/src/payto.ts b/packages/taler-util/src/payto.ts index dd764e42d..7dcb28098 100644 --- a/packages/taler-util/src/payto.ts +++ b/packages/taler-util/src/payto.ts @@ -49,9 +49,8 @@ export interface PaytoUriTalerBank extends PaytoUriGeneric { export interface PaytoUriBitcoin extends PaytoUriGeneric { isKnown: true; targetType: "bitcoin"; - generateSegwitAddress: (r: string) => { addr1: string; addr2: string }; - addr1?: string; - addr2?: string; + addr1: string; + addr2: string; } const paytoPfx = "payto://"; @@ -131,7 +130,7 @@ export function parsePaytoUri(s: string): PaytoUri | undefined { const searchParams = new URLSearchParams(search || ""); searchParams.forEach((v, k) => { - params[v] = k; + params[k] = v; }); if (targetType === "x-taler-bank") { @@ -157,15 +156,18 @@ export function parsePaytoUri(s: string): PaytoUri | undefined { }; } if (targetType === "bitcoin") { + const msg = /\b([A-Z0-9]{52})\b/.exec(params["message"]) + const reserve = !msg ? params["subject"] : msg[0]; + const { addr1, addr2 } = generateFakeSegwitAddress(reserve, targetPath); + const result: PaytoUriBitcoin = { isKnown: true, targetPath, targetType, params, - generateSegwitAddress: (): any => null, + addr1, addr2 }; - result.generateSegwitAddress = buildSegwitGenerator(result, targetPath); return result; } return { diff --git a/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx b/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx index ac6f8541e..b20fc2d59 100644 --- a/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx +++ b/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx @@ -45,10 +45,6 @@ export function BankDetailsByPaytoType({ if (payto.isKnown && payto.targetType === "bitcoin") { const min = segwitMinAmount(amount.currency); - if (typeof window !== "undefined") { - //FIXME: generate (and possibly save in db?) in wallet-core - payto.generateSegwitAddress(subject); - } return (

diff --git a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx index a8c6b3c1a..8b8d375de 100644 --- a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx @@ -66,9 +66,6 @@ export function ManualWithdrawPage({ currency, onCancel }: Props): VNode { ); const payto = response.exchangePaytoUris[0]; const paytoURI = parsePaytoUri(payto); - if (paytoURI && paytoURI.isKnown && paytoURI.targetType === "bitcoin") { - paytoURI.generateSegwitAddress(response.reservePub); - } setSuccess({ exchangeBaseUrl, response, amount, paytoURI, payto }); } catch (e) { if (e instanceof Error) {