From c16e85e485975e4615ec55c4298db640ce04456f Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Tue, 17 Oct 2017 12:20:24 -0700 Subject: [PATCH] wallet: all async methods. --- lib/wallet/account.js | 146 +++++++++++----------- lib/wallet/http.js | 10 +- lib/wallet/txdb.js | 1 - lib/wallet/wallet.js | 159 +++++++++++++++++------- lib/wallet/walletdb.js | 44 +++---- test/node-test.js | 20 +-- test/wallet-test.js | 269 ++++++++++++++++++++--------------------- 7 files changed, 347 insertions(+), 302 deletions(-) diff --git a/lib/wallet/account.js b/lib/wallet/account.js index 8e7f530e..d01bfea4 100644 --- a/lib/wallet/account.js +++ b/lib/wallet/account.js @@ -49,10 +49,6 @@ function Account(wdb, options) { this.wdb = wdb; this.network = wdb.network; - this.receive = null; - this.change = null; - this.nested = null; - this.wid = 0; this.id = null; this.name = null; @@ -242,27 +238,6 @@ Account.prototype.init = async function init(b) { await this.initDepth(b); }; -/** - * Open the account (done after retrieval). - * @returns {Promise} - */ - -Account.prototype.open = function open() { - if (!this.initialized) - return Promise.resolve(); - - if (this.receive) - return Promise.resolve(); - - this.receive = this.deriveReceive(this.receiveDepth - 1); - this.change = this.deriveChange(this.changeDepth - 1); - - if (this.witness) - this.nested = this.deriveNested(this.nestedDepth - 1); - - return Promise.resolve(); -}; - /** * Add a public account key to the account (multisig). * Does not update the database. @@ -600,10 +575,9 @@ Account.prototype.savePath = function savePath(b, path) { Account.prototype.initDepth = async function initDepth(b) { // Receive Address - this.receive = this.deriveReceive(0); this.receiveDepth = 1; - await this.saveKey(b, this.receive); + await this.saveKey(b, this.deriveReceive(0)); // Lookahead for (let i = 0; i < this.lookahead; i++) { @@ -612,10 +586,9 @@ Account.prototype.initDepth = async function initDepth(b) { } // Change Address - this.change = this.deriveChange(0); this.changeDepth = 1; - await this.saveKey(b, this.change); + await this.saveKey(b, this.deriveChange(0)); // Lookahead for (let i = 0; i < this.lookahead; i++) { @@ -625,10 +598,9 @@ Account.prototype.initDepth = async function initDepth(b) { // Nested Address if (this.witness) { - this.nested = this.deriveNested(0); this.nestedDepth = 1; - await this.saveKey(b, this.nested); + await this.saveKey(b, this.deriveNested(0)); // Lookahead for (let i = 0; i < this.lookahead; i++) { @@ -722,15 +694,11 @@ Account.prototype.setLookahead = async function setLookahead(b, lookahead) { const diff = this.lookahead - lookahead; this.receiveDepth += diff; - this.receive = this.deriveReceive(this.receiveDepth - 1); this.changeDepth += diff; - this.change = this.deriveChange(this.changeDepth - 1); - if (this.witness) { + if (this.witness) this.nestedDepth += diff; - this.nested = this.deriveNested(this.nestedDepth - 1); - } this.lookahead = lookahead; @@ -774,51 +742,84 @@ Account.prototype.setLookahead = async function setLookahead(b, lookahead) { }; /** - * Get current receive address. - * @param {String?} enc - `"base58"` or `null`. - * @returns {Address|Base58Address} + * Get current receive key. + * @returns {WalletKey} */ -Account.prototype.getAddress = function getAddress(enc) { - return this.getReceive(enc); +Account.prototype.receiveKey = function receiveKey() { + if (!this.initialized) + return null; + + return this.deriveReceive(this.receiveDepth - 1); +}; + +/** + * Get current change key. + * @returns {WalletKey} + */ + +Account.prototype.changeKey = function changeKey() { + if (!this.initialized) + return null; + + return this.deriveChange(this.changeDepth - 1); +}; + +/** + * Get current nested key. + * @returns {WalletKey} + */ + +Account.prototype.nestedKey = function nestedKey() { + if (!this.initialized) + return null; + + if (!this.witness) + return null; + + return this.deriveNested(this.nestedDepth - 1); }; /** * Get current receive address. - * @param {String?} enc - `"base58"` or `null`. - * @returns {Address|Base58Address} + * @returns {Address} */ -Account.prototype.getReceive = function getReceive(enc) { - if (!this.receive) +Account.prototype.receiveAddress = function receiveAddress() { + const key = this.receiveKey(); + + if (!key) return null; - return this.receive.getAddress(enc); + + return key.getAddress(); }; /** * Get current change address. - * @param {String?} enc - `"base58"` or `null`. - * @returns {Address|Base58Address} + * @returns {Address} */ -Account.prototype.getChange = function getChange(enc) { - if (!this.change) +Account.prototype.changeAddress = function changeAddress() { + const key = this.changeKey(); + + if (!key) return null; - return this.change.getAddress(enc); + return key.getAddress(); }; /** * Get current nested address. - * @param {String?} enc - `"base58"` or `null`. - * @returns {Address|Base58Address} + * @returns {Address} */ -Account.prototype.getNested = function getNested(enc) { - if (!this.nested) +Account.prototype.nestedAddress = function nestedAddress() { + const key = this.nestedKey(); + + if (!key) return null; - return this.nested.getAddress(enc); + return key.getAddress(); }; /** @@ -842,16 +843,11 @@ Account.prototype.inspect = function inspect() { changeDepth: this.changeDepth, nestedDepth: this.nestedDepth, lookahead: this.lookahead, - address: this.initialized - ? this.receive.getAddress() - : null, - nestedAddress: this.initialized && this.nested - ? this.nested.getAddress() - : null, + receiveAddress: this.receiveAddress(), + changeAddress: this.changeAddress(), + nestedAddress: this.nestedAddress(), accountKey: this.accountKey.toBase58(), - keys: this.keys.map((key) => { - return key.toBase58(); - }) + keys: this.keys.map(key => key.toBase58()) }; }; @@ -862,6 +858,10 @@ Account.prototype.inspect = function inspect() { */ Account.prototype.toJSON = function toJSON(minimal) { + const receive = this.receiveAddress(); + const change = this.changeAddress(); + const nested = this.nestedAddress(); + return { wid: minimal ? undefined : this.wid, id: minimal ? undefined : this.id, @@ -877,19 +877,11 @@ Account.prototype.toJSON = function toJSON(minimal) { changeDepth: this.changeDepth, nestedDepth: this.nestedDepth, lookahead: this.lookahead, - receiveAddress: this.receive - ? this.receive.getAddress('string') - : null, - nestedAddress: this.nested - ? this.nested.getAddress('string') - : null, - changeAddress: this.change - ? this.change.getAddress('string') - : null, + receiveAddress: receive ? receive.toString() : null, + changeAddress: change ? change.toString() : null, + nestedAddress: nested ? nested.toString() : null, accountKey: this.accountKey.toBase58(), - keys: this.keys.map((key) => { - return key.toBase58(); - }) + keys: this.keys.map(key => key.toBase58()) }; }; diff --git a/lib/wallet/http.js b/lib/wallet/http.js index dbcc2b7e..70adb1fd 100644 --- a/lib/wallet/http.js +++ b/lib/wallet/http.js @@ -308,7 +308,7 @@ HTTPServer.prototype.initRouter = function initRouter() { const passphrase = valid.str('passphrase'); const old = valid.str('old'); - enforce(old || new_, 'Passphrase is required.'); + enforce(passphrase, 'Passphrase is required.'); await req.wallet.setPassphrase(passphrase, old); @@ -715,7 +715,7 @@ HTTPServer.prototype.initRouter = function initRouter() { const result = []; for (const item of details) - result.push(item.toJSON()); + result.push(item.toJSON(this.network)); res.send(200, result); }); @@ -732,7 +732,7 @@ HTTPServer.prototype.initRouter = function initRouter() { const result = []; for (const item of details) - result.push(item.toJSON()); + result.push(item.toJSON(this.network)); res.send(200, result); }); @@ -754,7 +754,7 @@ HTTPServer.prototype.initRouter = function initRouter() { const result = []; for (const item of details) - result.push(item.toJSON()); + result.push(item.toJSON(this.network)); res.send(200, result); }); @@ -769,7 +769,7 @@ HTTPServer.prototype.initRouter = function initRouter() { const result = []; for (const item of details) - result.push(item.toJSON()); + result.push(item.toJSON(this.network)); res.send(200, result); }); diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index ab0cafbe..bf7c43d2 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -19,7 +19,6 @@ const records = require('./records'); const layout = require('./layout').txdb; const encoding = require('../utils/encoding'); const policy = require('../protocol/policy'); -const Script = require('../script/script'); const TXRecord = records.TXRecord; /** diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index 00d387b3..5e919262 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -13,7 +13,6 @@ const Network = require('../protocol/network'); const util = require('../utils/util'); const encoding = require('../utils/encoding'); const Lock = require('../utils/lock'); -const MappedLock = require('../utils/mappedlock'); const digest = require('../crypto/digest'); const cleanse = require('../crypto/cleanse'); const BufferReader = require('../utils/reader'); @@ -85,7 +84,6 @@ function Wallet(wdb, options) { this.master = new MasterKey(); this.txdb = new TXDB(this.wdb); - this.account = null; if (options) this.fromOptions(options); @@ -198,8 +196,6 @@ Wallet.prototype.init = async function init(options) { const account = await this._createAccount(options, passphrase); assert(account); - this.account = account; - this.logger.info('Wallet initialized (%s).', this.id); await this.txdb.open(this); @@ -218,8 +214,6 @@ Wallet.prototype.open = async function open() { if (!account) throw new Error('Default account not found.'); - this.account = account; - this.logger.info('Wallet opened (%s).', this.id); await this.txdb.open(this); @@ -723,11 +717,6 @@ Wallet.prototype.getAccountHashes = async function getAccountHashes(acct) { */ Wallet.prototype.getAccount = async function getAccount(acct) { - if (this.account) { - if (acct === 0 || acct === 'default') - return this.account; - } - const index = await this.getAccountIndex(acct); if (index === -1) @@ -742,8 +731,6 @@ Wallet.prototype.getAccount = async function getAccount(acct) { account.id = this.id; account.watchOnly = this.watchOnly; - await account.open(); - return account; }; @@ -1162,17 +1149,11 @@ Wallet.prototype._fund = async function _fund(mtx, options) { if (this.watchOnly) throw new Error('Cannot fund from watch-only wallet.'); - let account; - if (options.account != null) { - account = await this.getAccount(options.account); - if (!account) - throw new Error('Account not found.'); - } else { - account = this.account; - } + const acct = options.account || 0; + const change = await this.changeAddress(acct); - if (!account.initialized) - throw new Error('Account is not initialized.'); + if (!change) + throw new Error('Account not found.'); let rate = options.rate; if (rate == null) @@ -1193,7 +1174,7 @@ Wallet.prototype._fund = async function _fund(mtx, options) { hardFee: options.hardFee, subtractFee: options.subtractFee, subtractIndex: options.subtractIndex, - changeAddress: account.change.getAddress(), + changeAddress: change, height: this.wdb.state.height, rate: rate, maxFee: options.maxFee, @@ -2155,43 +2136,133 @@ Wallet.prototype.getLast = async function getLast(acct, limit) { }; /** - * Get current receive address. - * @param {String?} enc - `"base58"` or `null`. - * @returns {Address|Base58Address} + * Get account key. + * @param {Number} [acct=0] + * @returns {HDPublicKey} */ -Wallet.prototype.getAddress = function getAddress(enc) { - return this.account.getAddress(enc); +Wallet.prototype.accountKey = async function accountKey(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.accountKey; +}; + +/** + * Get current receive depth. + * @param {Number} [acct=0] + * @returns {Number} + */ + +Wallet.prototype.receiveDepth = async function receiveDepth(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.receiveDepth; +}; + +/** + * Get current change depth. + * @param {Number} [acct=0] + * @returns {Number} + */ + +Wallet.prototype.changeDepth = async function changeDepth(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.changeDepth; +}; + +/** + * Get current nested depth. + * @param {Number} [acct=0] + * @returns {Number} + */ + +Wallet.prototype.nestedDepth = async function nestedDepth(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.nestedDepth; }; /** * Get current receive address. - * @param {String?} enc - `"base58"` or `null`. - * @returns {Address|Base58Address} + * @param {Number} [acct=0] + * @returns {Address} */ -Wallet.prototype.getReceive = function getReceive(enc) { - return this.account.getReceive(enc); +Wallet.prototype.receiveAddress = async function receiveAddress(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.receiveAddress(); }; /** * Get current change address. - * @param {String?} enc - `"base58"` or `null`. - * @returns {Address|Base58Address} + * @param {Number} [acct=0] + * @returns {Address} */ -Wallet.prototype.getChange = function getChange(enc) { - return this.account.getChange(enc); +Wallet.prototype.changeAddress = async function changeAddress(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.changeAddress(); }; /** * Get current nested address. - * @param {String?} enc - `"base58"` or `null`. - * @returns {Address|Base58Address} + * @param {Number} [acct=0] + * @returns {Address} */ -Wallet.prototype.getNested = function getNested(enc) { - return this.account.getNested(enc); +Wallet.prototype.nestedAddress = async function nestedAddress(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.nestedAddress(); +}; + +/** + * Get current receive key. + * @param {Number} [acct=0] + * @returns {WalletKey} + */ + +Wallet.prototype.receiveKey = async function receiveKey(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.receiveKey(); +}; + +/** + * Get current change key. + * @param {Number} [acct=0] + * @returns {WalletKey} + */ + +Wallet.prototype.changeKey = async function changeKey(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.changeKey(); +}; + +/** + * Get current nested key. + * @param {Number} [acct=0] + * @returns {WalletKey} + */ + +Wallet.prototype.nestedKey = async function nestedKey(acct = 0) { + const account = await this.getAccount(acct); + if (!account) + throw new Error('Account not found.'); + return account.nestedKey(); }; /** @@ -2209,8 +2280,7 @@ Wallet.prototype.inspect = function inspect() { token: this.token.toString('hex'), tokenDepth: this.tokenDepth, state: this.txdb.state ? this.txdb.state.toJSON(true) : null, - master: this.master, - account: this.account + master: this.master }; }; @@ -2233,8 +2303,7 @@ Wallet.prototype.toJSON = function toJSON(unsafe) { token: this.token.toString('hex'), tokenDepth: this.tokenDepth, state: this.txdb.state.toJSON(true), - master: this.master.toJSON(unsafe), - account: this.account.toJSON(true) + master: this.master.toJSON(unsafe) }; }; diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index 4e9f2ea3..2e512b39 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -136,7 +136,7 @@ WalletDB.prototype._open = async function _open() { await this.logger.open(); await this.db.open(); - await this.db.checkVersion('V', 6); + await this.db.checkVersion('V', 7); this.depth = await this.getDepth(); @@ -157,7 +157,7 @@ WalletDB.prototype._open = async function _open() { this.logger.info( 'Loaded primary wallet (id=%s, wid=%d, address=%s)', - wallet.id, wallet.wid, wallet.getAddress()); + wallet.id, wallet.wid, await wallet.receiveAddress()); this.primary = wallet; this.rpc.wallet = wallet; @@ -1299,15 +1299,14 @@ WalletDB.prototype.decryptKeys = async function decryptKeys(b, wid, key) { */ WalletDB.prototype.resend = async function resend() { - const keys = await this.db.keys({ + const wids = await this.db.keys({ gte: layout.w(0x00000000), - lte: layout.w(0xffffffff) + lte: layout.w(0xffffffff), + parse: k => layout.ww(k) }); - for (const key of keys) { - const wid = layout.ww(key); + for (const wid of wids) await this.resendPending(wid); - } }; /** @@ -1319,26 +1318,27 @@ WalletDB.prototype.resend = async function resend() { WalletDB.prototype.resendPending = async function resendPending(wid) { const layout = layouts.txdb; + const prefix = layout.prefix(wid); + const b = this.db.bucket(prefix); - const keys = await this.db.keys({ - gte: layout.prefix(wid, layout.p(encoding.NULL_HASH)), - lte: layout.prefix(wid, layout.p(encoding.HIGH_HASH)) + const hashes = await b.keys({ + gte: layout.p(encoding.NULL_HASH), + lte: layout.p(encoding.HIGH_HASH), + parse: k => layout.pp(k) }); - if (keys.length === 0) + if (hashes.length === 0) return; this.logger.info( 'Rebroadcasting %d transactions for %d.', - keys.length, + hashes.length, wid); const txs = []; - for (const key of keys) { - const hash = layout.pp(key); - const tkey = layout.prefix(wid, layout.t(hash)); - const data = await this.db.get(tkey); + for (const hash of hashes) { + const data = await b.get(layout.t(hash)); if (!data) continue; @@ -1718,7 +1718,7 @@ WalletDB.prototype.rollback = async function rollback(height) { if (height === this.state.height) { this.logger.debug('Rolled back to same height (%d).', height); - return true; + return; } this.logger.info( @@ -1730,8 +1730,6 @@ WalletDB.prototype.rollback = async function rollback(height) { await this.revert(tip.height); await this.syncState(tip); - - return true; }; /** @@ -2011,13 +2009,7 @@ WalletDB.prototype._resetChain = async function _resetChain(entry) { if (entry.height > this.state.height) throw new Error('WDB: Bad reset height.'); - // Try to rollback. - if (await this.rollback(entry.height)) - return; - - // If we rolled back to the - // start block, we need a rescan. - await this.scan(); + await this.rollback(entry.height); }; /** diff --git a/test/node-test.js b/test/node-test.js index f2551107..3bac5733 100644 --- a/test/node-test.js +++ b/test/node-test.js @@ -44,8 +44,8 @@ async function mineBlock(tip, tx) { spend.addTX(tx, 0); - spend.addOutput(wallet.getReceive(), 25 * 1e8); - spend.addOutput(wallet.getChange(), 5 * 1e8); + spend.addOutput(await wallet.receiveAddress(), 25 * 1e8); + spend.addOutput(await wallet.changeAddress(), 5 * 1e8); spend.setLocktime(chain.height); @@ -94,7 +94,7 @@ describe('Node', function() { it('should open walletdb', async () => { wallet = await wdb.create(); miner.addresses.length = 0; - miner.addAddress(wallet.getReceive()); + miner.addAddress(await wallet.receiveAddress()); }); it('should mine a block', async () => { @@ -258,8 +258,8 @@ describe('Node', function() { assert.strictEqual(balance.unconfirmed, 1250 * 1e8); assert.strictEqual(balance.confirmed, 750 * 1e8); - assert(wallet.account.receiveDepth >= 7); - assert(wallet.account.changeDepth >= 6); + assert((await wallet.receiveDepth()) >= 7); + assert((await wallet.changeDepth()) >= 6); assert.strictEqual(wdb.state.height, chain.height); @@ -447,7 +447,7 @@ describe('Node', function() { it('should rescan for transactions', async () => { await wdb.rescan(0); - assert.strictEqual(wallet.txdb.state.confirmed, 1289250000000); + assert.strictEqual((await wallet.getBalance()).confirmed, 1289250000000); }); it('should reset miner mempool', async () => { @@ -572,7 +572,7 @@ describe('Node', function() { rate: 100000, outputs: [{ value: 100000, - address: wallet.getAddress() + address: await wallet.receiveAddress() }] }); @@ -582,7 +582,7 @@ describe('Node', function() { const tx = mtx.toTX(); - await wallet.wdb.addTX(tx); + await wdb.addTX(tx); const missing = await node.mempool.addTX(tx); assert(!missing); @@ -597,7 +597,7 @@ describe('Node', function() { rate: 1000, outputs: [{ value: 50000, - address: wallet.getAddress() + address: await wallet.receiveAddress() }] }); @@ -607,7 +607,7 @@ describe('Node', function() { const tx = mtx.toTX(); - await wallet.wdb.addTX(tx); + await wdb.addTX(tx); const missing = await node.mempool.addTX(tx); assert(!missing); diff --git a/test/wallet-test.js b/test/wallet-test.js index d76ba203..5df77e45 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -37,11 +37,6 @@ let importedKey = null; let doubleSpendWallet = null; let doubleSpendCoin = null; -function prevBlock(wdb) { - assert(wdb.state.height > 0); - return fakeBlock(wdb.state.height - 1); -}; - function curBlock(wdb) { return fakeBlock(wdb.state.height); }; @@ -73,21 +68,24 @@ function dummyInput() { async function testP2PKH(witness, nesting) { const flags = Script.flags.STANDARD_VERIFY_FLAGS; + const receiveAddress = nesting ? 'nestedAddress' : 'receiveAddress'; + const type = witness ? Address.types.WITNESS : Address.types.PUBKEYHASH; const wallet = await wdb.create({ witness }); - const addr = Address.fromString(wallet.getAddress('string')); + const waddr = await wallet.receiveAddress(); + const addr = Address.fromString(waddr.toString()); - const type = witness ? Address.types.WITNESS : Address.types.PUBKEYHASH; assert.strictEqual(addr.type, type); + assert.strictEqual(addr.type, waddr.type); const src = new MTX(); src.addInput(dummyInput()); - src.addOutput(nesting ? wallet.getNested() : wallet.getAddress(), 5460 * 2); + src.addOutput(await wallet[receiveAddress](), 5460 * 2); src.addOutput(new Address(), 2 * 5460); const mtx = new MTX(); mtx.addTX(src, 0); - mtx.addOutput(wallet.getAddress(), 5460); + mtx.addOutput(await wallet.receiveAddress(), 5460); await wallet.sign(mtx); @@ -98,7 +96,7 @@ async function testP2PKH(witness, nesting) { async function testP2SH(witness, nesting) { const flags = Script.flags.STANDARD_VERIFY_FLAGS; - const receive = nesting ? 'nested' : 'receive'; + const receiveAddress = nesting ? 'nestedAddress' : 'receiveAddress'; const receiveDepth = nesting ? 'nestedDepth' : 'receiveDepth'; const vector = witness ? 'witness' : 'script'; @@ -115,17 +113,17 @@ async function testP2SH(witness, nesting) { const carol = await wdb.create(options); const recipient = await wdb.create(); - await alice.addSharedKey(0, bob.account.accountKey); - await alice.addSharedKey(0, carol.account.accountKey); + await alice.addSharedKey(0, await bob.accountKey(0)); + await alice.addSharedKey(0, await carol.accountKey(0)); - await bob.addSharedKey(0, alice.account.accountKey); - await bob.addSharedKey(0, carol.account.accountKey); + await bob.addSharedKey(0, await alice.accountKey(0)); + await bob.addSharedKey(0, await carol.accountKey(0)); - await carol.addSharedKey(0, alice.account.accountKey); - await carol.addSharedKey(0, bob.account.accountKey); + await carol.addSharedKey(0, await alice.accountKey(0)); + await carol.addSharedKey(0, await bob.accountKey(0)); // Our p2sh address - const addr1 = alice.account[receive].getAddress(); + const addr1 = await alice[receiveAddress](); if (witness) { const type = nesting ? Address.types.SCRIPTHASH : Address.types.WITNESS; @@ -134,17 +132,17 @@ async function testP2SH(witness, nesting) { assert.strictEqual(addr1.type, Address.types.SCRIPTHASH); } - assert(alice.account[receive].getAddress().equals(addr1)); - assert(bob.account[receive].getAddress().equals(addr1)); - assert(carol.account[receive].getAddress().equals(addr1)); + assert((await alice[receiveAddress]()).equals(addr1)); + assert((await bob[receiveAddress]()).equals(addr1)); + assert((await carol[receiveAddress]()).equals(addr1)); - const nestedAddr1 = alice.getNested(); + const nestedAddr1 = await alice.nestedAddress(); if (witness) { assert(nestedAddr1); - assert(alice.getNested().equals(nestedAddr1)); - assert(bob.getNested().equals(nestedAddr1)); - assert(carol.getNested().equals(nestedAddr1)); + assert((await alice.nestedAddress()).equals(nestedAddr1)); + assert((await bob.nestedAddress()).equals(nestedAddr1)); + assert((await carol.nestedAddress()).equals(nestedAddr1)); } { @@ -154,25 +152,25 @@ async function testP2SH(witness, nesting) { fund.addOutput(nesting ? nestedAddr1 : addr1, 5460 * 10); // Simulate a confirmation - assert.strictEqual(alice.account[receiveDepth], 1); + assert.strictEqual(await alice[receiveDepth](), 1); await wdb.addBlock(nextBlock(wdb), [fund.toTX()]); - assert.strictEqual(alice.account[receiveDepth], 2); - assert.strictEqual(alice.account.changeDepth, 1); + assert.strictEqual(await alice[receiveDepth](), 2); + assert.strictEqual(await alice.changeDepth(), 1); } - const addr2 = alice.account[receive].getAddress(); + const addr2 = await alice[receiveAddress](); assert(!addr2.equals(addr1)); - assert(alice.account[receive].getAddress().equals(addr2)); - assert(bob.account[receive].getAddress().equals(addr2)); - assert(carol.account[receive].getAddress().equals(addr2)); + assert((await alice[receiveAddress]()).equals(addr2)); + assert((await bob[receiveAddress]()).equals(addr2)); + assert((await carol[receiveAddress]()).equals(addr2)); // Create a tx requiring 2 signatures const send = new MTX(); - send.addOutput(recipient.getAddress(), 5460); + send.addOutput(await recipient.receiveAddress(), 5460); assert(!send.verify(flags)); @@ -190,30 +188,30 @@ async function testP2SH(witness, nesting) { const [tx, view] = send.commit(); assert(tx.verify(view, flags)); - assert.strictEqual(alice.account.changeDepth, 1); + assert.strictEqual(await alice.changeDepth(), 1); - const change = alice.account.change.getAddress(); + const change = await alice.changeAddress(); - assert(alice.account.change.getAddress().equals(change)); - assert(bob.account.change.getAddress().equals(change)); - assert(carol.account.change.getAddress().equals(change)); + assert((await alice.changeAddress()).equals(change)); + assert((await bob.changeAddress()).equals(change)); + assert((await carol.changeAddress()).equals(change)); // Simulate a confirmation { await wdb.addBlock(nextBlock(wdb), [tx]); - assert.strictEqual(alice.account[receiveDepth], 2); - assert.strictEqual(alice.account.changeDepth, 2); + assert.strictEqual(await alice[receiveDepth](), 2); + assert.strictEqual(await alice.changeDepth(), 2); - assert(alice.account[receive].getAddress().equals(addr2)); - assert(!alice.account.change.getAddress().equals(change)); + assert((await alice[receiveAddress]()).equals(addr2)); + assert(!(await alice.changeAddress()).equals(change)); } - const change2 = alice.account.change.getAddress(); + const change2 = await alice.changeAddress(); - assert(alice.account.change.getAddress().equals(change2)); - assert(bob.account.change.getAddress().equals(change2)); - assert(carol.account.change.getAddress().equals(change2)); + assert((await alice.changeAddress()).equals(change2)); + assert((await bob.changeAddress()).equals(change2)); + assert((await carol.changeAddress()).equals(change2)); const input = tx.inputs[0]; input[vector].setData(2, encoding.ZERO_SIG); @@ -234,7 +232,7 @@ describe('Wallet', function() { it('should generate new key and address', async () => { const wallet = await wdb.create(); - const addr1 = wallet.getAddress(); + const addr1 = await wallet.receiveAddress(); assert(addr1); const str = addr1.toString(); @@ -284,7 +282,7 @@ describe('Wallet', function() { await wallet.addSharedKey(0, key); const script = Script.fromMultisig(1, 2, [ - wallet.account.receive.getPublicKey(), + (await wallet.receiveKey()).publicKey, key.derivePath('m/0/0').publicKey ]); @@ -296,7 +294,7 @@ describe('Wallet', function() { const tx = new MTX(); tx.addTX(src, 0); - tx.addOutput(wallet.getAddress(), 5460); + tx.addOutput(await wallet.receiveAddress(), 5460); const maxSize = await tx.estimateSize(); @@ -306,7 +304,7 @@ describe('Wallet', function() { assert(tx.verify()); }); - it('should handle missed and invalid txs', async () => { + it('should handle missed txs', async () => { const alice = await wdb.create(); const bob = await wdb.create(); @@ -314,13 +312,13 @@ describe('Wallet', function() { // balance: 51000 const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(alice.getAddress(), 50000); - t1.addOutput(alice.getAddress(), 1000); + t1.addOutput(await alice.receiveAddress(), 50000); + t1.addOutput(await alice.receiveAddress(), 1000); const t2 = new MTX(); t2.addTX(t1, 0); // 50000 - t2.addOutput(alice.getAddress(), 24000); - t2.addOutput(alice.getAddress(), 24000); + t2.addOutput(await alice.receiveAddress(), 24000); + t2.addOutput(await alice.receiveAddress(), 24000); // Save for later. doubleSpendWallet = alice; @@ -332,7 +330,7 @@ describe('Wallet', function() { const t3 = new MTX(); t3.addTX(t1, 1); // 1000 t3.addTX(t2, 0); // 24000 - t3.addOutput(alice.getAddress(), 23000); + t3.addOutput(await alice.receiveAddress(), 23000); // balance: 47000 await alice.sign(t3); @@ -340,15 +338,15 @@ describe('Wallet', function() { const t4 = new MTX(); t4.addTX(t2, 1); // 24000 t4.addTX(t3, 0); // 23000 - t4.addOutput(alice.getAddress(), 11000); - t4.addOutput(alice.getAddress(), 11000); + t4.addOutput(await alice.receiveAddress(), 11000); + t4.addOutput(await alice.receiveAddress(), 11000); // balance: 22000 await alice.sign(t4); const f1 = new MTX(); f1.addTX(t4, 1); // 11000 - f1.addOutput(bob.getAddress(), 10000); + f1.addOutput(await bob.receiveAddress(), 10000); // balance: 11000 await alice.sign(f1); @@ -433,7 +431,6 @@ describe('Wallet', function() { return wtx.tx.hash('hex') === f1.hash('hex'); })); } - }); it('should cleanup spenders after double-spend', async () => { @@ -461,7 +458,7 @@ describe('Wallet', function() { { const tx = new MTX(); tx.addCoin(doubleSpendCoin); - tx.addOutput(wallet.getAddress(), 5000); + tx.addOutput(await wallet.receiveAddress(), 5000); await wallet.sign(tx); @@ -482,22 +479,22 @@ describe('Wallet', function() { } }); - it('should handle missed txs without resolution', async () => { + it('should handle more missed txs', async () => { const alice = await wdb.create(); const bob = await wdb.create(); // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(alice.getAddress(), 50000); - t1.addOutput(alice.getAddress(), 1000); + t1.addOutput(await alice.receiveAddress(), 50000); + t1.addOutput(await alice.receiveAddress(), 1000); // balance: 51000 const t2 = new MTX(); t2.addTX(t1, 0); // 50000 - t2.addOutput(alice.getAddress(), 24000); - t2.addOutput(alice.getAddress(), 24000); + t2.addOutput(await alice.receiveAddress(), 24000); + t2.addOutput(await alice.receiveAddress(), 24000); // balance: 49000 await alice.sign(t2); @@ -505,7 +502,7 @@ describe('Wallet', function() { const t3 = new MTX(); t3.addTX(t1, 1); // 1000 t3.addTX(t2, 0); // 24000 - t3.addOutput(alice.getAddress(), 23000); + t3.addOutput(await alice.receiveAddress(), 23000); // balance: 47000 await alice.sign(t3); @@ -513,15 +510,15 @@ describe('Wallet', function() { const t4 = new MTX(); t4.addTX(t2, 1); // 24000 t4.addTX(t3, 0); // 23000 - t4.addOutput(alice.getAddress(), 11000); - t4.addOutput(alice.getAddress(), 11000); + t4.addOutput(await alice.receiveAddress(), 11000); + t4.addOutput(await alice.receiveAddress(), 11000); // balance: 22000 await alice.sign(t4); const f1 = new MTX(); f1.addTX(t4, 1); // 11000 - f1.addOutput(bob.getAddress(), 10000); + f1.addOutput(await bob.receiveAddress(), 10000); // balance: 11000 await alice.sign(f1); @@ -599,16 +596,16 @@ describe('Wallet', function() { // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); // Create new transaction const m2 = new MTX(); - m2.addOutput(bob.getAddress(), 5460); + m2.addOutput(await bob.receiveAddress(), 5460); await alice.fund(m2, { rate: 10000, @@ -627,7 +624,7 @@ describe('Wallet', function() { // Create new transaction const t3 = new MTX(); - t3.addOutput(bob.getAddress(), 15000); + t3.addOutput(await bob.receiveAddress(), 15000); let err; try { @@ -655,16 +652,16 @@ describe('Wallet', function() { // Coinbase const t1 = new MTX(); t1.addOutpoint(new Outpoint(encoding.NULL_HASH, 0)); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); // Create new transaction const m2 = new MTX(); - m2.addOutput(bob.getAddress(), 5460); + m2.addOutput(await bob.receiveAddress(), 5460); await alice.fund(m2, { rate: 10000 @@ -697,7 +694,7 @@ describe('Wallet', function() { // Create new transaction const t3 = new MTX(); - t3.addOutput(bob.getAddress(), 15000); + t3.addOutput(await bob.receiveAddress(), 15000); let err; try { @@ -721,25 +718,25 @@ describe('Wallet', function() { // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); // Coinbase const t2 = new MTX(); t2.addInput(dummyInput()); - t2.addOutput(bob.getAddress(), 5460); - t2.addOutput(bob.getAddress(), 5460); - t2.addOutput(bob.getAddress(), 5460); - t2.addOutput(bob.getAddress(), 5460); + t2.addOutput(await bob.receiveAddress(), 5460); + t2.addOutput(await bob.receiveAddress(), 5460); + t2.addOutput(await bob.receiveAddress(), 5460); + t2.addOutput(await bob.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); await wdb.addTX(t2.toTX()); // Create our tx with an output const tx = new MTX(); - tx.addOutput(carol.getAddress(), 5460); + tx.addOutput(await carol.receiveAddress(), 5460); const coins1 = await alice.getCoins(); const coins2 = await bob.getCoins(); @@ -799,16 +796,16 @@ describe('Wallet', function() { // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(account.receive.getAddress(), 5460); - t1.addOutput(account.receive.getAddress(), 5460); - t1.addOutput(account.receive.getAddress(), 5460); - t1.addOutput(account.receive.getAddress(), 5460); + t1.addOutput(account.receiveAddress(), 5460); + t1.addOutput(account.receiveAddress(), 5460); + t1.addOutput(account.receiveAddress(), 5460); + t1.addOutput(account.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); // Create new transaction const t2 = new MTX(); - t2.addOutput(bob.getAddress(), 5460); + t2.addOutput(await bob.receiveAddress(), 5460); await alice.fund(t2, { rate: 10000, @@ -825,7 +822,7 @@ describe('Wallet', function() { // Create new transaction const t3 = new MTX(); - t3.addOutput(bob.getAddress(), 15000); + t3.addOutput(await bob.receiveAddress(), 15000); let err; try { @@ -858,27 +855,23 @@ describe('Wallet', function() { const account = await wallet.getAccount('foo'); assert.strictEqual(account.name, 'foo'); assert.strictEqual(account.accountIndex, 1); - assert.strictEqual(wallet.account.accountIndex, 0); - assert(!account.receive.getAddress().equals( - wallet.account.receive.getAddress())); - - assert(wallet.getAddress().equals(wallet.account.receive.getAddress())); + assert(!account.receiveAddress().equals(await wallet.receiveAddress())); // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(wallet.getAddress(), 5460); - t1.addOutput(wallet.getAddress(), 5460); - t1.addOutput(wallet.getAddress(), 5460); - t1.addOutput(account.receive.getAddress(), 5460); + t1.addOutput(await wallet.receiveAddress(), 5460); + t1.addOutput(await wallet.receiveAddress(), 5460); + t1.addOutput(await wallet.receiveAddress(), 5460); + t1.addOutput(account.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); // Should fill from `foo` and fail const t2 = new MTX(); - t2.addOutput(wallet.getAddress(), 5460); + t2.addOutput(await wallet.receiveAddress(), 5460); let err; try { @@ -895,7 +888,7 @@ describe('Wallet', function() { // Should fill from whole wallet and succeed const t3 = new MTX(); - t3.addOutput(wallet.getAddress(), 5460); + t3.addOutput(await wallet.receiveAddress(), 5460); await wallet.fund(t3, { rate: 10000, @@ -905,15 +898,15 @@ describe('Wallet', function() { // Coinbase const t4 = new MTX(); t4.addInput(dummyInput()); - t4.addOutput(account.receive.getAddress(), 5460); - t4.addOutput(account.receive.getAddress(), 5460); - t4.addOutput(account.receive.getAddress(), 5460); + t4.addOutput(await wallet.receiveAddress('foo'), 5460); + t4.addOutput(await wallet.receiveAddress('foo'), 5460); + t4.addOutput(await wallet.receiveAddress('foo'), 5460); await wdb.addTX(t4.toTX()); // Should fill from `foo` and succeed const t5 = new MTX(); - t5.addOutput(wallet.getAddress(), 5460); + t5.addOutput(await wallet.receiveAddress(), 5460); await wallet.fund(t5, { rate: 10000, @@ -959,16 +952,16 @@ describe('Wallet', function() { // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(wallet.getAddress(), 5460); - t1.addOutput(wallet.getAddress(), 5460); - t1.addOutput(wallet.getAddress(), 5460); - t1.addOutput(wallet.getAddress(), 5460); + t1.addOutput(await wallet.receiveAddress(), 5460); + t1.addOutput(await wallet.receiveAddress(), 5460); + t1.addOutput(await wallet.receiveAddress(), 5460); + t1.addOutput(await wallet.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); // Create new transaction const t2 = new MTX(); - t2.addOutput(wallet.getAddress(), 5460); + t2.addOutput(await wallet.receiveAddress(), 5460); await wallet.fund(t2, { rate: 10000, @@ -998,16 +991,16 @@ describe('Wallet', function() { // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); // Create new transaction const t2 = new MTX(); - t2.addOutput(bob.getAddress(), 21840); + t2.addOutput(await bob.receiveAddress(), 21840); await alice.fund(t2, { rate: 10000, @@ -1031,10 +1024,10 @@ describe('Wallet', function() { // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); @@ -1042,7 +1035,7 @@ describe('Wallet', function() { subtractFee: true, rate: 10000, round: true, - outputs: [{ address: bob.getAddress(), value: 21840 }] + outputs: [{ address: await bob.receiveAddress(), value: 21840 }] }; // Create new transaction @@ -1063,20 +1056,20 @@ describe('Wallet', function() { // Coinbase const t1 = new MTX(); t1.addInput(dummyInput()); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); - t1.addOutput(alice.getAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); + t1.addOutput(await alice.receiveAddress(), 5460); await wdb.addTX(t1.toTX()); // Coinbase const t2 = new MTX(); t2.addInput(dummyInput()); - t2.addOutput(alice.getAddress(), 5460); - t2.addOutput(alice.getAddress(), 5460); - t2.addOutput(alice.getAddress(), 5460); - t2.addOutput(alice.getAddress(), 5460); + t2.addOutput(await alice.receiveAddress(), 5460); + t2.addOutput(await alice.receiveAddress(), 5460); + t2.addOutput(await alice.receiveAddress(), 5460); + t2.addOutput(await alice.receiveAddress(), 5460); await wdb.addBlock(nextBlock(wdb), [t2.toTX()]); @@ -1095,7 +1088,7 @@ describe('Wallet', function() { subtractFee: true, rate: 1000, depth: 1, - outputs: [{ address: bob.getAddress(), value: 1461 }] + outputs: [{ address: await bob.receiveAddress(), value: 1461 }] }); const coins = await alice.getSmartCoins(); @@ -1127,7 +1120,7 @@ describe('Wallet', function() { smart: true, rate: 10000, outputs: [{ - address: bob.getAddress(), + address: await bob.receiveAddress(), value: total }] }; @@ -1228,7 +1221,7 @@ describe('Wallet', function() { rate: 10000, round: true, outputs: [{ - address: wallet.getAddress(), + address: await wallet.receiveAddress(), value: 7000 }] }; @@ -1357,7 +1350,7 @@ describe('Wallet', function() { master: KEY1 }); - const addr = alice.getAddress(); + const addr = await alice.receiveAddress(); // Coinbase const t1 = new MTX(); @@ -1417,7 +1410,7 @@ describe('Wallet', function() { master: KEY1 }); - const addr = alice.getAddress(); + const addr = await alice.receiveAddress(); // Coinbase const t1 = new MTX();