From 1696b3c7bb4cee3dea7d89b96b7d7c2220c5f175 Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Thu, 22 Nov 2018 23:36:48 -0800 Subject: [PATCH 1/3] wallet: require pubkey for watchonly --- lib/wallet/wallet.js | 2 +- test/wallet-test.js | 42 ++++++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index e6ed64dc8..daf8f5af8 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -575,7 +575,7 @@ class Wallet extends EventEmitter { await this.unlock(passphrase); let key; - if (this.watchOnly && options.accountKey) { + if (this.watchOnly) { key = options.accountKey; if (typeof key === 'string') diff --git a/test/wallet-test.js b/test/wallet-test.js index 035ecf5a4..9f2fba8c7 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -18,6 +18,7 @@ const Input = require('../lib/primitives/input'); const Outpoint = require('../lib/primitives/outpoint'); const Script = require('../lib/script/script'); const HD = require('../lib/hd'); +const PrivateKey = require('../lib/hd/private'); const KEY1 = 'xprv9s21ZrQH143K3Aj6xQBymM31Zb4BVc7wxqfUhMZrzewdDVCt' + 'qUP9iWfcHgJofs25xbaUpCps9GDXj83NiWvQCAkWQhVj5J4CorfnpKX94AZ'; @@ -34,6 +35,7 @@ let importedWallet = null; let importedKey = null; let doubleSpendWallet = null; let doubleSpendCoin = null; +let watchWallet = null; function fromU32(num) { const data = Buffer.allocUnsafe(4); @@ -1301,37 +1303,49 @@ describe('Wallet', function() { importedKey = key; }); + it('should require account key to create watch only wallet', async () => { + try { + watchWallet = await wdb.create({ + watchOnly: true + }); + } catch (e) { + assert.strictEqual( + e.message, + 'Must add HD public keys to watch only wallet.' + ); + } + + const privateKey = PrivateKey.generate(); + const xpub = privateKey.xpubkey('main'); + watchWallet = await wdb.create({ + watchOnly: true, + accountKey: xpub + }); + }); + it('should import pubkey', async () => { const key = KeyRing.generate(); const pub = new KeyRing(key.publicKey); - const wallet = await wdb.create({ - watchOnly: true - }); + await watchWallet.importKey('default', pub); - await wallet.importKey('default', pub); - - const path = await wallet.getPath(pub.getHash()); + const path = await watchWallet.getPath(pub.getHash()); assert.bufferEqual(path.hash, pub.getHash()); - const wkey = await wallet.getKey(pub.getHash()); + const wkey = await watchWallet.getKey(pub.getHash()); assert(wkey); }); it('should import address', async () => { const key = KeyRing.generate(); - const wallet = await wdb.create({ - watchOnly: true - }); - - await wallet.importAddress('default', key.getAddress()); + await watchWallet.importAddress('default', key.getAddress()); - const path = await wallet.getPath(key.getHash()); + const path = await watchWallet.getPath(key.getHash()); assert(path); assert.bufferEqual(path.hash, key.getHash()); - const wkey = await wallet.getKey(key.getHash()); + const wkey = await watchWallet.getKey(key.getHash()); assert(!wkey); }); From 0090c597144f2e2a217301e445af51876556f5e4 Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Fri, 4 Jan 2019 10:00:13 -0800 Subject: [PATCH 2/3] changelog: update for watch-only --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84f4f56b1..e695ac510 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Bcoin Release Notes & Changelog +## v1.0.x + +### Wallet API changes + +Creating a watch-only wallet now requires an `account-key` (or `accountKey`) +argument. This is to prevent bcoin from generating keys and addresses the user +can not spend from. + ## v1.0.0 ### Migration From bf32e86abe92232b71d9a0d6372f18bd4c87807d Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Mon, 11 Feb 2019 13:30:40 -0800 Subject: [PATCH 3/3] test: independent watch-only tests and assert error --- test/wallet-test.js | 48 +++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/test/wallet-test.js b/test/wallet-test.js index 9f2fba8c7..98d3ee0d8 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -18,7 +18,6 @@ const Input = require('../lib/primitives/input'); const Outpoint = require('../lib/primitives/outpoint'); const Script = require('../lib/script/script'); const HD = require('../lib/hd'); -const PrivateKey = require('../lib/hd/private'); const KEY1 = 'xprv9s21ZrQH143K3Aj6xQBymM31Zb4BVc7wxqfUhMZrzewdDVCt' + 'qUP9iWfcHgJofs25xbaUpCps9GDXj83NiWvQCAkWQhVj5J4CorfnpKX94AZ'; @@ -26,6 +25,10 @@ const KEY1 = 'xprv9s21ZrQH143K3Aj6xQBymM31Zb4BVc7wxqfUhMZrzewdDVCt' const KEY2 = 'xprv9s21ZrQH143K3mqiSThzPtWAabQ22Pjp3uSNnZ53A5bQ4udp' + 'faKekc2m4AChLYH1XDzANhrSdxHYWUeTWjYJwFwWFyHkTMnMeAcW4JyRCZa'; +// abandon abandon... about key at m'/44'/0'/0' +const PUBKEY = 'xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhaw' + + 'A7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj'; + const enabled = true; const workers = new WorkerPool({ enabled }); const wdb = new WalletDB({ workers }); @@ -35,7 +38,6 @@ let importedWallet = null; let importedKey = null; let doubleSpendWallet = null; let doubleSpendCoin = null; -let watchWallet = null; function fromU32(num) { const data = Buffer.allocUnsafe(4); @@ -1304,48 +1306,56 @@ describe('Wallet', function() { }); it('should require account key to create watch only wallet', async () => { + let err = null; + try { - watchWallet = await wdb.create({ + await wdb.create({ watchOnly: true }); } catch (e) { - assert.strictEqual( - e.message, - 'Must add HD public keys to watch only wallet.' - ); + err = e; } - const privateKey = PrivateKey.generate(); - const xpub = privateKey.xpubkey('main'); - watchWallet = await wdb.create({ - watchOnly: true, - accountKey: xpub - }); + assert(err); + assert.strictEqual( + err.message, + 'Must add HD public keys to watch only wallet.' + ); }); it('should import pubkey', async () => { const key = KeyRing.generate(); const pub = new KeyRing(key.publicKey); - await watchWallet.importKey('default', pub); + const wallet = await wdb.create({ + watchOnly: true, + accountKey: PUBKEY + }); + + await wallet.importKey('default', pub); - const path = await watchWallet.getPath(pub.getHash()); + const path = await wallet.getPath(pub.getHash()); assert.bufferEqual(path.hash, pub.getHash()); - const wkey = await watchWallet.getKey(pub.getHash()); + const wkey = await wallet.getKey(pub.getHash()); assert(wkey); }); it('should import address', async () => { const key = KeyRing.generate(); - await watchWallet.importAddress('default', key.getAddress()); + const wallet = await wdb.create({ + watchOnly: true, + accountKey: PUBKEY + }); + + await wallet.importAddress('default', key.getAddress()); - const path = await watchWallet.getPath(key.getHash()); + const path = await wallet.getPath(key.getHash()); assert(path); assert.bufferEqual(path.hash, key.getHash()); - const wkey = await watchWallet.getKey(key.getHash()); + const wkey = await wallet.getKey(key.getHash()); assert(!wkey); });