From 2e56a82280f3fae029ddd90ab5c837206bd9a2ce Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 17 Oct 2016 22:09:29 -0700 Subject: [PATCH] txdb: handle state and balance differently. --- lib/primitives/address.js | 12 +-- lib/wallet/txdb.js | 163 ++++++++++++-------------------------- 2 files changed, 57 insertions(+), 118 deletions(-) diff --git a/lib/primitives/address.js b/lib/primitives/address.js index 82d62ff1..6cb1ea2f 100644 --- a/lib/primitives/address.js +++ b/lib/primitives/address.js @@ -551,18 +551,18 @@ Address.getHash = function getHash(data, enc) { if (typeof data === 'string') { if (data.length === 40 || data.length === 64) return enc === 'hex' ? data : new Buffer(data, 'hex'); - } - if (Buffer.isBuffer(data)) { - hash = data; - } else if (data instanceof Address) { - hash = data.hash; - } else { try { hash = Address.fromBase58(data).hash; } catch (e) { return; } + } else if (Buffer.isBuffer(data)) { + hash = data; + } else if (data instanceof Address) { + hash = data.hash; + } else { + return; } return enc === 'hex' diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index 4be6f556..5f85dd1c 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -217,7 +217,6 @@ function TXDB(wallet) { this.locked = {}; this.state = null; - this.balance = null; this.pending = null; this.events = []; @@ -249,15 +248,13 @@ TXDB.prototype.open = co(function* open() { this.logger.info('TXDB created for %s.', this.wallet.id); } - this.balance = this.state.balance; - this.logger.info('TXDB State: tx=%d coin=%s.', this.state.tx, this.state.coin); this.logger.info( 'Balance: unconfirmed=%s confirmed=%s.', - utils.btc(this.balance.unconfirmed), - utils.btc(this.balance.confirmed)); + utils.btc(this.state.unconfirmed), + utils.btc(this.state.confirmed)); }); /** @@ -312,7 +309,6 @@ TXDB.prototype.commit = co(function* commit() { // with our new committed state. if (this.pending.committed) { this.state = this.pending; - this.balance = this.state.balance; // Emit buffered events now that // we know everything is written. @@ -478,7 +474,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx) { var hash = tx.hash('hex'); var hasOrphans = false; var orphans = []; - var i, input, prevout, address; + var i, input, prevout; var path, key, coin, spent; if (tx.isCoinbase()) @@ -494,9 +490,6 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx) { spent = yield this.isSpent(prevout.hash, prevout.index); if (spent) { - if (tx.height === -1) - return false; - coin = yield this.getSpentCoin(spent, prevout); assert(coin); @@ -523,8 +516,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx) { continue; } - address = input.getHash('hex'); - path = yield this.wallet.hasPath(address); + path = yield this.wallet.hasPath(input.getAddress()); if (!path) continue; @@ -761,16 +753,17 @@ TXDB.prototype._add = co(function* add(tx, info) { this.put(layout.s(prevout.hash, prevout.index), spender); - this.pending.balance.unconfirmed -= coin.value; + this.pending.unconfirmed -= coin.value; if (tx.height === -1) { this.put(layout.S(prevout.hash, prevout.index), spender); this.spentCache.set(key, spender); } else { - this.pending.balance.confirmed -= coin.value; + this.pending.confirmed -= coin.value; this.del(layout.c(prevout.hash, prevout.index)); this.del(layout.C(path.account, prevout.hash, prevout.index)); this.coinCache.remove(key); + this.pending.coin--; } this.put(layout.d(hash, i), coin.toRaw()); @@ -791,13 +784,14 @@ TXDB.prototype._add = co(function* add(tx, info) { coin = Coin.fromTX(tx, i); raw = coin.toRaw(); - this.pending.balance.unconfirmed += coin.value; + this.pending.unconfirmed += coin.value; if (tx.height !== -1) - this.pending.balance.confirmed += coin.value; + this.pending.confirmed += coin.value; this.put(layout.c(hash, i), raw); this.put(layout.C(path.account, hash, i), DUMMY); + this.pending.coin++; this.coinCache.set(key, raw); } @@ -813,7 +807,7 @@ TXDB.prototype._add = co(function* add(tx, info) { if (tx.height !== -1) this.emit('confirmed', tx, info); - this.emit('balance', this.pending.balance, info); + this.emit('balance', this.pending.toBalance(), info); return true; }); @@ -1017,7 +1011,7 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) { this.put(layout.d(hash, i), coin.toRaw()); this.put(layout.s(prevout.hash, prevout.index), spender); - this.pending.balance.unconfirmed -= coin.value; + this.pending.unconfirmed -= coin.value; } assert(coin.height !== -1); @@ -1032,7 +1026,8 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) { this.del(layout.c(prevout.hash, prevout.index)); this.del(layout.C(path.account, prevout.hash, prevout.index)); - this.pending.balance.confirmed -= coin.value; + this.pending.coin--; + this.pending.confirmed -= coin.value; this.spentCache.remove(key); this.coinCache.remove(key); @@ -1058,7 +1053,8 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) { coin.height = tx.height; raw = coin.toRaw(); - this.pending.balance.confirmed += coin.value; + this.pending.confirmed += coin.value; + this.pending.coin++; this.put(layout.c(hash, i), raw); @@ -1072,7 +1068,7 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) { this.emit('tx', tx, info); this.emit('confirmed', tx, info); - this.emit('balance', this.pending.balance, info); + this.emit('balance', this.pending.toBalance(), info); return true; }); @@ -1192,13 +1188,14 @@ TXDB.prototype.__remove = co(function* remove(tx, info) { path = info.getPath(coin); assert(path); - this.pending.balance.unconfirmed += coin.value; + this.pending.unconfirmed += coin.value; this.del(layout.s(prevout.hash, prevout.index)); if (tx.height !== -1) { raw = coin.toRaw(); - this.pending.balance.confirmed += coin.value; + this.pending.confirmed += coin.value; + this.pending.coin++; this.put(layout.c(prevout.hash, prevout.index), raw); this.put(layout.C(path.account, prevout.hash, prevout.index), DUMMY); this.coinCache.set(key, raw); @@ -1221,10 +1218,11 @@ TXDB.prototype.__remove = co(function* remove(tx, info) { coin = Coin.fromTX(tx, i); - this.pending.balance.unconfirmed -= coin.value; + this.pending.coin--; + this.pending.unconfirmed -= coin.value; if (tx.height !== -1) - this.pending.balance.confirmed -= coin.value; + this.pending.confirmed -= coin.value; this.del(layout.c(hash, i)); this.del(layout.C(path.account, hash, i)); @@ -1236,7 +1234,7 @@ TXDB.prototype.__remove = co(function* remove(tx, info) { this.put(layout.R, this.pending.commit()); this.emit('remove tx', tx, info); - this.emit('balance', this.pending.balance, info); + this.emit('balance', this.pending.toBalance(), info); return info; }); @@ -1345,7 +1343,8 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) { this.put(layout.c(prevout.hash, prevout.index), raw); this.put(layout.C(path.account, prevout.hash, prevout.index), DUMMY); - this.pending.balance.confirmed += coin.value; + this.pending.coin++; + this.pending.confirmed += coin.value; this.spentCache.set(key, spender); this.coinCache.set(key, raw); @@ -1365,18 +1364,20 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) { continue; coin.height = -1; + raw = coin.toRaw(); - this.pending.balance.confirmed -= coin.value; + this.pending.confirmed -= coin.value; + this.pending.coin++; - this.put(layout.c(hash, i), coin.toRaw()); + this.put(layout.c(hash, i), raw); - this.coinCache.remove(key); + this.coinCache.set(key, raw); } this.put(layout.R, this.pending.commit()); this.emit('unconfirmed', tx, info); - this.emit('balance', this.pending.balance, info); + this.emit('balance', this.pending.toBalance(), info); return info; }); @@ -2185,7 +2186,7 @@ TXDB.prototype.getBalance = co(function* getBalance(account) { return yield this.getAccountBalance(account); // Fast case - return this.balance; + return this.state.toBalance(); }); /** @@ -2248,8 +2249,7 @@ TXDB.prototype.zap = co(function* zap(account, age) { var now = utils.now(); var i, txs, tx, hash; - if (!utils.isUInt32(age)) - throw new Error('Age must be a number.'); + assert(utils.isUInt32(age)); txs = yield this.getRange(account, { start: 0, @@ -2304,66 +2304,12 @@ function Balance(wid, id, account) { this.confirmed = 0; } -Balance.prototype.clone = function clone() { - var balance = new Balance(this.wid, this.id, this.account); - balance.unconfirmed = this.unconfirmed; - balance.confirmed = this.confirmed; - return balance; -}; - Balance.prototype.equal = function equal(balance) { return this.wid === balance.wid && this.confirmed === balance.confirmed && this.unconfirmed === balance.unconfirmed; }; -Balance.prototype.add = function add(coin) { - if (coin.height === -1) - this.unconfirmed += coin.value; - else - this.confirmed += coin.value; -}; - -Balance.prototype.sub = function sub(coin) { - if (coin.height === -1) - this.unconfirmed -= coin.value; - else - this.confirmed -= coin.value; -}; - -Balance.prototype.confirm = function confirm(value) { - this.unconfirmed -= value; - this.confirmed += value; -}; - -Balance.prototype.unconfirm = function unconfirm(value) { - this.unconfirmed += value; - this.confirmed -= value; -}; - -Balance.prototype.toRaw = function toRaw(writer) { - var p = new BufferWriter(writer); - - p.writeU64(this.unconfirmed); - p.writeU64(this.confirmed); - - if (!writer) - p = p.render(); - - return p; -}; - -Balance.prototype.fromRaw = function fromRaw(data) { - var p = new BufferReader(data); - this.unconfirmed = p.readU53(); - this.confirmed = p.readU53(); - return this; -}; - -Balance.fromRaw = function fromRaw(wid, id, data) { - return new Balance(wid, id, -1).fromRaw(data); -}; - Balance.prototype.toJSON = function toJSON(minimal) { return { wid: !minimal ? this.wid : undefined, @@ -2395,7 +2341,8 @@ function TXDBState(wid, id) { this.id = id; this.tx = 0; this.coin = 0; - this.balance = new Balance(wid, id, -1); + this.unconfirmed = 0; + this.confirmed = 0; this.committed = false; } @@ -2403,7 +2350,8 @@ TXDBState.prototype.clone = function clone() { var state = new TXDBState(this.wid, this.id); state.tx = this.tx; state.coin = this.coin; - state.balance = this.balance.clone(); + state.unconfirmed = this.unconfirmed; + state.confirmed = this.confirmed; return state; }; @@ -2412,12 +2360,20 @@ TXDBState.prototype.commit = function commit() { return this.toRaw(); }; +TXDBState.prototype.toBalance = function toBalance() { + var balance = new Balance(this.wid, this.id, -1); + balance.unconfirmed = this.unconfirmed; + balance.confirmed = this.confirmed; + return balance; +}; + TXDBState.prototype.toRaw = function toRaw(writer) { var p = new BufferWriter(writer); p.writeU64(this.tx); p.writeU64(this.coin); - this.balance.toRaw(p); + p.writeU64(this.unconfirmed); + p.writeU64(this.confirmed); if (!writer) p = p.render(); @@ -2429,7 +2385,8 @@ TXDBState.prototype.fromRaw = function fromRaw(data) { var p = new BufferReader(data); this.tx = p.readU53(); this.coin = p.readU53(); - this.balance.fromRaw(p); + this.unconfirmed = p.readU53(); + this.confirmed = p.readU53(); return this; }; @@ -2437,32 +2394,14 @@ TXDBState.fromRaw = function fromRaw(wid, id, data) { return new TXDBState(wid, id).fromRaw(data); }; -TXDBState.prototype.add = function add(coin) { - this.coin++; - return this.balance.add(coin); -}; - -TXDBState.prototype.sub = function sub(coin) { - this.coin--; - return this.balance.sub(coin); -}; - -TXDBState.prototype.confirm = function confirm(value) { - return this.balance.confirm(value); -}; - -TXDBState.prototype.unconfirm = function unconfirm(value) { - return this.balance.unconfirm(value); -}; - TXDBState.prototype.toJSON = function toJSON(minimal) { return { wid: !minimal ? this.wid : undefined, id: !minimal ? this.id : undefined, tx: this.tx, coin: this.coin, - unconfirmed: utils.btc(this.balance.unconfirmed), - confirmed: utils.btc(this.balance.confirmed) + unconfirmed: utils.btc(this.unconfirmed), + confirmed: utils.btc(this.confirmed) }; };