mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2024-11-19 18:00:17 +01:00
FIX: crashes after importing malformed xpub as watch-only (closes #1399)
This commit is contained in:
parent
110c801dde
commit
12016f1277
@ -229,6 +229,9 @@ export class AppStorage {
|
||||
case WatchOnlyWallet.type:
|
||||
unserializedWallet = WatchOnlyWallet.fromJson(key);
|
||||
unserializedWallet.init();
|
||||
if (unserializedWallet.isHd() && !unserializedWallet.isXpubValid()) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case HDLegacyP2PKHWallet.type:
|
||||
unserializedWallet = HDLegacyP2PKHWallet.fromJson(key);
|
||||
|
@ -971,20 +971,6 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
||||
}).address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts zpub to xpub
|
||||
*
|
||||
* @param {String} zpub
|
||||
* @returns {String} xpub
|
||||
*/
|
||||
static _zpubToXpub(zpub) {
|
||||
let data = b58.decode(zpub);
|
||||
data = data.slice(4);
|
||||
data = Buffer.concat([Buffer.from('0488b21e', 'hex'), data]);
|
||||
|
||||
return b58.encode(data);
|
||||
}
|
||||
|
||||
static _getTransactionsFromHistories(histories) {
|
||||
const txs = [];
|
||||
for (const history of Object.values(histories)) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
||||
import b58 from 'bs58check';
|
||||
const createHash = require('create-hash');
|
||||
|
||||
export class AbstractWallet {
|
||||
@ -217,4 +218,32 @@ export class AbstractWallet {
|
||||
async wasEverUsed() {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts zpub to xpub
|
||||
*
|
||||
* @param {String} zpub
|
||||
* @returns {String} xpub
|
||||
*/
|
||||
static _zpubToXpub(zpub) {
|
||||
let data = b58.decode(zpub);
|
||||
data = data.slice(4);
|
||||
data = Buffer.concat([Buffer.from('0488b21e', 'hex'), data]);
|
||||
|
||||
return b58.encode(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts ypub to xpub
|
||||
* @param {String} ypub - wallet ypub
|
||||
* @returns {*}
|
||||
*/
|
||||
static _ypubToXpub(ypub) {
|
||||
let data = b58.decode(ypub);
|
||||
if (data.readUInt32BE() !== 0x049d7cb2) throw new Error('Not a valid ypub extended key!');
|
||||
data = data.slice(4);
|
||||
data = Buffer.concat([Buffer.from('0488b21e', 'hex'), data]);
|
||||
|
||||
return b58.encode(data);
|
||||
}
|
||||
}
|
||||
|
@ -121,20 +121,6 @@ export class HDSegwitP2SHWallet extends AbstractHDElectrumWallet {
|
||||
return psbt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts ypub to xpub
|
||||
* @param {String} ypub - wallet ypub
|
||||
* @returns {*}
|
||||
*/
|
||||
static _ypubToXpub(ypub) {
|
||||
let data = b58.decode(ypub);
|
||||
if (data.readUInt32BE() !== 0x049d7cb2) throw new Error('Not a valid ypub extended key!');
|
||||
data = data.slice(4);
|
||||
data = Buffer.concat([Buffer.from('0488b21e', 'hex'), data]);
|
||||
|
||||
return b58.encode(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Segwit P2SH Bitcoin address
|
||||
* @param hdNode
|
||||
|
@ -3,6 +3,7 @@ import { HDSegwitP2SHWallet } from './hd-segwit-p2sh-wallet';
|
||||
import { HDLegacyP2PKHWallet } from './hd-legacy-p2pkh-wallet';
|
||||
import { HDSegwitBech32Wallet } from './hd-segwit-bech32-wallet';
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
const HDNode = require('bip32');
|
||||
|
||||
export class WatchOnlyWallet extends LegacyWallet {
|
||||
static type = 'watchOnly';
|
||||
@ -41,7 +42,7 @@ export class WatchOnlyWallet extends LegacyWallet {
|
||||
}
|
||||
|
||||
valid() {
|
||||
if (this.secret.startsWith('xpub') || this.secret.startsWith('ypub') || this.secret.startsWith('zpub')) return true;
|
||||
if (this.secret.startsWith('xpub') || this.secret.startsWith('ypub') || this.secret.startsWith('zpub')) return this.isXpubValid();
|
||||
|
||||
try {
|
||||
bitcoin.address.toOutputScript(this.getAddress());
|
||||
@ -213,4 +214,24 @@ export class WatchOnlyWallet extends LegacyWallet {
|
||||
setUseWithHardwareWalletEnabled(enabled) {
|
||||
this.use_with_hardware_wallet = !!enabled;
|
||||
}
|
||||
|
||||
isXpubValid() {
|
||||
let xpub;
|
||||
|
||||
try {
|
||||
if (this.secret.startsWith('zpub')) {
|
||||
xpub = this.constructor._zpubToXpub(this.secret);
|
||||
} else if (this.secret.startsWith('ypub')) {
|
||||
xpub = this.constructor._ypubToXpub(this.secret);
|
||||
} else {
|
||||
xpub = this.secret;
|
||||
}
|
||||
|
||||
const hdNode = HDNode.fromBase58(xpub);
|
||||
hdNode.derive(0);
|
||||
return true;
|
||||
} catch (_) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -29,9 +29,26 @@ describe('Watch only wallet', () => {
|
||||
assert.strictEqual(w.isHd(), true);
|
||||
assert.strictEqual(w.getMasterFingerprint(), false);
|
||||
assert.strictEqual(w.getMasterFingerprintHex(), '00000000');
|
||||
assert.ok(w.isXpubValid(), w.secret);
|
||||
}
|
||||
});
|
||||
|
||||
it('can validate xpub', () => {
|
||||
const w = new WatchOnlyWallet();
|
||||
w.setSecret('xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps');
|
||||
assert.ok(w.isXpubValid());
|
||||
w.setSecret('ypub6XRzrn3HB1tjhhvrHbk1vnXCecZEdXohGzCk3GXwwbDoJ3VBzZ34jNGWbC6WrS7idXrYjjXEzcPDX5VqnHEnuNf5VAXgLfSaytMkJ2rwVqy');
|
||||
assert.ok(w.isXpubValid());
|
||||
w.setSecret('zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP');
|
||||
assert.ok(w.isXpubValid());
|
||||
w.setSecret('xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6D');
|
||||
assert.ok(!w.isXpubValid());
|
||||
w.setSecret('ypub6XRzrn3HB1tjhhvrHbk1vnXCecZEdXohGzCk3GXwwbDoJ3VBzZ34jNGWbC6WrS7idXr');
|
||||
assert.ok(!w.isXpubValid());
|
||||
w.setSecret('ypub6XRzrn3HB1tjhhvrHbk1vnXCecZEdXohGzCk3GXwwbDoJ3VBzZ34jNGWbC6WrS7idXr');
|
||||
assert.ok(!w.isXpubValid());
|
||||
});
|
||||
|
||||
it('can create PSBT base64 without signature for HW wallet', async () => {
|
||||
const w = new WatchOnlyWallet();
|
||||
w.setSecret('zpub6rjLjQVqVnj7crz9E4QWj4WgczmEseJq22u2B6k2HZr6NE2PQx3ZYg8BnbjN9kCfHymSeMd2EpwpM5iiz5Nrb3TzvddxW2RMcE3VXdVaXHk');
|
||||
|
Loading…
Reference in New Issue
Block a user