diff --git a/lib/wallet/records.js b/lib/wallet/records.js index a5d8d0836..a36f39d0e 100644 --- a/lib/wallet/records.js +++ b/lib/wallet/records.js @@ -217,16 +217,20 @@ class TXRecord extends bio.Struct { /** * Create tx record. * @constructor - * @param {TX} tx - * @param {BlockMeta?} block + * @param {Number} mtime + * @param {TX} [tx] + * @param {BlockMeta} [block] */ - constructor(tx, block) { + constructor(mtime, tx, block) { super(); + if (mtime == null) + mtime = util.now(); + this.tx = null; this.hash = null; - this.mtime = util.now(); + this.mtime = mtime; this.height = -1; this.block = null; this.index = -1; @@ -240,7 +244,7 @@ class TXRecord extends bio.Struct { * Inject properties from tx and block. * @private * @param {TX} tx - * @param {Block?} block + * @param {Block} [block] * @returns {TXRecord} */ @@ -256,13 +260,14 @@ class TXRecord extends bio.Struct { /** * Instantiate tx record from tx and block. - * @param {TX} tx - * @param {Block?} block + * @param {TX} [tx] + * @param {Block} [block] + * @param {Number} [mtime] * @returns {TXRecord} */ - static fromTX(tx, block) { - return new this().fromTX(tx, block); + static fromTX(tx, block, mtime) { + return new this(mtime).fromTX(tx, block); } /** diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index a1e53ab4f..f92ef8103 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -46,6 +46,7 @@ class TXDB { this.wdb = wdb; this.db = wdb.db; this.logger = wdb.logger; + this.nowFn = wdb.options.nowFn || util.now; this.wid = wid || 0; this.bucket = null; @@ -809,7 +810,8 @@ class TXDB { return this.confirm(existing, block); } - const wtx = TXRecord.fromTX(tx, block); + const now = this.nowFn(); + const wtx = TXRecord.fromTX(tx, block, now); if (!block) { // Potentially remove double-spenders. @@ -3252,7 +3254,7 @@ class TXDB { async zap(acct, age) { assert((age >>> 0) === age); - const now = util.now(); + const now = this.nowFn(); const txs = await this.getRange(acct, { start: 0, diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index 790087b41..0bafc9db9 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -29,6 +29,7 @@ const WalletMigrator = require('./migrations'); const layout = layouts.wdb; const tlayout = layouts.txdb; const {states} = require('../covenants/namestate'); +const util = require('../utils/util'); const { ChainState, @@ -2582,6 +2583,8 @@ class WalletOptions { this.migrateNoRescan = false; this.preloadAll = false; + this.nowFn = util.now; + if (options) this.fromOptions(options); } @@ -2678,6 +2681,11 @@ class WalletOptions { this.preloadAll = options.preloadAll; } + if (options.timeFn != null) { + assert(typeof options.timeFn === 'function'); + this.nowFn = options.timeFn; + } + return this; } diff --git a/test/wallet-records-test.js b/test/wallet-records-test.js index 2d59c9ff9..744282551 100644 --- a/test/wallet-records-test.js +++ b/test/wallet-records-test.js @@ -56,15 +56,18 @@ function getRandomTXRecordData(genTX = false, genBlock = false) { if (genTX) tx = getRandomTX(); + const mtime = random.randomInt(); + const data = { height: block ? block.height : -1, time: block ? block.time : 0, block: block ? block.hash : null, tx: tx, - hash: tx ? tx.hash() : null + hash: tx ? tx.hash() : null, + mtime: mtime }; - return {data, tx, block}; + return {data, tx, block, mtime}; } /* @@ -114,6 +117,7 @@ function compareTXRecord(actual, expected) { assert(typeof actual.mtime === 'number'); assert(actual.mtime > 0); + assert.strictEqual(actual.mtime, expected.mtime); assert.strictEqual(actual.index, -1); } @@ -267,16 +271,28 @@ describe('Wallet Records', function() { }); }); + it('should initialize w/ time', () => { + const {mtime} = getRandomTXRecordData(false, false, true); + const wtx = new TXRecord(mtime); + + compareTXRecord(wtx, { + index: -1, + mtime: mtime, + ...emptyTX, + ...emptyBlock + }); + }); + it('should initialize w/ tx', () => { - const {data, tx} = getRandomTXRecordData(true); - const wtx = new TXRecord(tx); + const {data, tx, mtime} = getRandomTXRecordData(true); + const wtx = new TXRecord(mtime, tx); compareTXRecord(wtx, data); }); it('should initialize w/ tx and block', () => { - const {data, block, tx} = getRandomTXRecordData(true, true); - const wtx = new TXRecord(tx, block); + const {data, block, tx, mtime} = getRandomTXRecordData(true, true); + const wtx = new TXRecord(mtime, tx, block); compareTXRecord(wtx, data); }); @@ -294,9 +310,9 @@ describe('Wallet Records', function() { }); it('should encode/decode w/ tx', () => { - const {data, tx} = getRandomTXRecordData(true); + const {data, tx, mtime} = getRandomTXRecordData(true); - const wtx = new TXRecord(tx); + const wtx = new TXRecord(mtime, tx); const encoded = wtx.encode(); const decoded = TXRecord.decode(encoded); @@ -305,9 +321,9 @@ describe('Wallet Records', function() { }); it('should encode/decode w/ tx and block', () => { - const {data, tx, block} = getRandomTXRecordData(true, true); + const {data, tx, block, mtime} = getRandomTXRecordData(true, true); - const wtx = new TXRecord(tx, block); + const wtx = new TXRecord(mtime, tx, block); const encoded = wtx.encode(); const decoded = TXRecord.decode(encoded); @@ -316,20 +332,20 @@ describe('Wallet Records', function() { }); it('should initialize from TX', () => { - const {data, tx} = getRandomTXRecordData(true); - const wtx = TXRecord.fromTX(tx); + const {data, tx, mtime} = getRandomTXRecordData(true); + const wtx = TXRecord.fromTX(tx, null, mtime); compareTXRecord(wtx, data); }); it('should initialize from TX and Block', () => { - const {data, tx, block} = getRandomTXRecordData(true, true); - const wtx = TXRecord.fromTX(tx, block); + const {data, tx, block, mtime} = getRandomTXRecordData(true, true); + const wtx = TXRecord.fromTX(tx, block, mtime); compareTXRecord(wtx, data); }); it('should set and unset block', () => { - const {data, tx, block} = getRandomTXRecordData(true, true); - const wtx = TXRecord.fromTX(tx); + const {data, tx, block, mtime} = getRandomTXRecordData(true, true); + const wtx = TXRecord.fromTX(tx, null, mtime); assert.strictEqual(wtx.getBlock(), null); assert.strictEqual(wtx.getDepth(random.randomInt()), 0); diff --git a/test/wallet-test.js b/test/wallet-test.js index b7b267c1e..868b7644b 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -1998,7 +1998,7 @@ describe('Wallet', function() { }); it('should throw error with missing outputs', async () => { - const wallet = new Wallet({}); + const wallet = new Wallet({ options: {} }); let err = null; @@ -2012,6 +2012,17 @@ describe('Wallet', function() { assert.equal(err.message, 'At least one output is required.'); }); + it('should pass nowFn to the txdb', async () => { + const nowFn = () => 1; + const wallet = new Wallet({ + options: { + nowFn + } + }); + + assert.strictEqual(wallet.txdb.nowFn(), nowFn()); + }); + it('should cleanup', async () => { network.coinbaseMaturity = 2; await wdb.close();