refactor: chain. txdb. wallet.

This commit is contained in:
Christopher Jeffrey 2016-09-22 23:58:19 -07:00
parent 63a9dc61f6
commit c2e1e4bfc9
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
13 changed files with 152 additions and 171 deletions

View File

@ -117,8 +117,4 @@ var runBench = co(function* runBench() {
end(1); end(1);
}); });
runBench().then(process.exit).catch(function(err) { runBench().then(process.exit);
utils.nextTick(function() {
throw err;
});
});

View File

@ -52,7 +52,6 @@ known-peers: ./known-peers
# Miner # Miner
# payout-address: 1111111111111111111114oLvT2 # payout-address: 1111111111111111111114oLvT2
# coinbase-flags: mined by bcoin # coinbase-flags: mined by bcoin
# parallel: false
# HTTP # HTTP
# ssl-cert: @/ssl/cert.crt # ssl-cert: @/ssl/cert.crt

View File

@ -1008,7 +1008,9 @@ Chain.prototype.isBusy = function isBusy() {
Chain.prototype.add = co(function* add(block) { Chain.prototype.add = co(function* add(block) {
var unlock = yield this.locker.lock(block); var unlock = yield this.locker.lock(block);
this.currentBlock = block.hash('hex'); this.currentBlock = block.hash('hex');
try { try {
return yield this._add(block); return yield this._add(block);
} finally { } finally {
@ -1232,7 +1234,7 @@ Chain.prototype._add = co(function* add(block) {
* @returns {Boolean} * @returns {Boolean}
*/ */
Chain.prototype._isSlow = function _isSlow() { Chain.prototype.isSlow = function isSlow() {
if (this.options.spv) if (this.options.spv)
return false; return false;
@ -1265,7 +1267,7 @@ Chain.prototype.finish = function finish(block, entry) {
// Keep track of total blocks handled. // Keep track of total blocks handled.
this.total += 1; this.total += 1;
if (!this._isSlow()) if (!this.isSlow())
return; return;
// Report memory for debugging. // Report memory for debugging.
@ -1777,8 +1779,7 @@ Chain.prototype.getState = co(function* getState(prev, id) {
var timeStart, timeTimeout, compute, height; var timeStart, timeTimeout, compute, height;
var i, entry, count, state, block, medianTime; var i, entry, count, state, block, medianTime;
if (!deployment) assert(deployment);
return constants.thresholdStates.FAILED;
timeStart = deployment.startTime; timeStart = deployment.startTime;
timeTimeout = deployment.timeout; timeTimeout = deployment.timeout;
@ -1791,11 +1792,10 @@ Chain.prototype.getState = co(function* getState(prev, id) {
height = prev.height - ((prev.height + 1) % period); height = prev.height - ((prev.height + 1) % period);
prev = yield prev.getAncestorByHeight(height); prev = yield prev.getAncestorByHeight(height);
if (!prev) if (prev) {
return constants.thresholdStates.FAILED; assert(prev.height === height);
assert(((prev.height + 1) % period) === 0);
assert(prev.height === height); }
assert(((prev.height + 1) % period) === 0);
} }
entry = prev; entry = prev;
@ -1811,6 +1811,7 @@ Chain.prototype.getState = co(function* getState(prev, id) {
if (medianTime < timeStart) { if (medianTime < timeStart) {
state = constants.thresholdStates.DEFINED; state = constants.thresholdStates.DEFINED;
stateCache[entry.hash] = state;
break; break;
} }
@ -1830,58 +1831,50 @@ Chain.prototype.getState = co(function* getState(prev, id) {
if (medianTime >= timeTimeout) { if (medianTime >= timeTimeout) {
state = constants.thresholdStates.FAILED; state = constants.thresholdStates.FAILED;
stateCache[entry.hash] = state; break;
continue;
} }
if (medianTime >= timeStart) { if (medianTime >= timeStart) {
state = constants.thresholdStates.STARTED; state = constants.thresholdStates.STARTED;
stateCache[entry.hash] = state; break;
continue;
} }
stateCache[entry.hash] = state; break;
continue;
case constants.thresholdStates.STARTED: case constants.thresholdStates.STARTED:
medianTime = yield entry.getMedianTimeAsync(); medianTime = yield entry.getMedianTimeAsync();
if (medianTime >= timeTimeout) { if (medianTime >= timeTimeout) {
state = constants.thresholdStates.FAILED; state = constants.thresholdStates.FAILED;
stateCache[entry.hash] = state;
break; break;
} }
i = 0;
count = 0;
block = entry; block = entry;
count = 0;
while (block) { for (i = 0; i < period; i++) {
if (i++ >= period) if (block.hasBit(deployment))
break;
if (hasBit(block, deployment))
count++; count++;
block = yield block.getPrevious(); block = yield block.getPrevious();
assert(block);
} }
if (count >= threshold) if (count >= threshold)
state = constants.thresholdStates.LOCKED_IN; state = constants.thresholdStates.LOCKED_IN;
stateCache[entry.hash] = state;
break; break;
case constants.thresholdStates.LOCKED_IN: case constants.thresholdStates.LOCKED_IN:
state = constants.thresholdStates.ACTIVE; state = constants.thresholdStates.ACTIVE;
stateCache[entry.hash] = state;
break; break;
case constants.thresholdStates.FAILED: case constants.thresholdStates.FAILED:
case constants.thresholdStates.ACTIVE: case constants.thresholdStates.ACTIVE:
stateCache[entry.hash] = state;
break; break;
default: default:
assert(false, 'Bad state.'); assert(false, 'Bad state.');
break; break;
} }
stateCache[entry.hash] = state;
} }
return state; return state;
@ -1984,7 +1977,7 @@ Chain.prototype.getLocks = co(function* getLocks(prev, tx, flags) {
var i, input, entry; var i, input, entry;
if (tx.isCoinbase() || tx.version < 2 || !hasFlag) if (tx.isCoinbase() || tx.version < 2 || !hasFlag)
return [minHeight, minTime]; return new LockTimes(minHeight, minTime);
for (i = 0; i < tx.inputs.length; i++) { for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i]; input = tx.inputs[i];
@ -1992,9 +1985,9 @@ Chain.prototype.getLocks = co(function* getLocks(prev, tx, flags) {
if (input.sequence & disableFlag) if (input.sequence & disableFlag)
continue; continue;
coinHeight = input.coin.height === -1 coinHeight = input.coin.height !== -1
? this.height + 1 ? input.coin.height
: input.coin.height; : this.height + 1;
if ((input.sequence & typeFlag) === 0) { if ((input.sequence & typeFlag) === 0) {
coinHeight += (input.sequence & mask) - 1; coinHeight += (input.sequence & mask) - 1;
@ -2010,7 +2003,7 @@ Chain.prototype.getLocks = co(function* getLocks(prev, tx, flags) {
minTime = Math.max(minTime, coinTime); minTime = Math.max(minTime, coinTime);
} }
return [minHeight, minTime]; return new LockTimes(minHeight, minTime);
}); });
/** /**
@ -2048,9 +2041,7 @@ Chain.prototype.evalLocks = co(function* evalLocks(prev, minHeight, minTime) {
Chain.prototype.checkLocks = co(function* checkLocks(prev, tx, flags) { Chain.prototype.checkLocks = co(function* checkLocks(prev, tx, flags) {
var times = yield this.getLocks(prev, tx, flags); var times = yield this.getLocks(prev, tx, flags);
var minHeight = times[0]; return yield this.evalLocks(prev, times.height, times.time);
var minTime = times[1];
return yield this.evalLocks(prev, minHeight, minTime);
}); });
/** /**
@ -2135,14 +2126,12 @@ DeploymentState.prototype.hasWitness = function hasWitness() {
}; };
/* /*
* Helpers * LockTimes
*/ */
function hasBit(entry, deployment) { function LockTimes(height, time) {
var bits = entry.version & constants.versionbits.TOP_MASK; this.height = height;
var topBits = constants.versionbits.TOP_BITS; this.time = time;
var mask = 1 << deployment.bit;
return bits === topBits && (entry.version & mask) !== 0;
} }
/* /*

View File

@ -417,7 +417,8 @@ ChainEntry.prototype.isSuperMajorityAsync = co(function* isSuperMajorityAsync(ve
}); });
/** /**
* Test whether the entry is potentially an ancestor of a checkpoint. * Test whether the entry is potentially
* an ancestor of a checkpoint.
* @returns {Boolean} * @returns {Boolean}
*/ */
@ -429,6 +430,19 @@ ChainEntry.prototype.isHistorical = function isHistorical() {
return false; return false;
}; };
/**
* Test whether the entry contains a version bit.
* @param {Object} deployment
* @returns {Boolean}
*/
ChainEntry.prototype.hasBit = function hasBit(deployment) {
var bits = this.version & constants.versionbits.TOP_MASK;
var topBits = constants.versionbits.TOP_BITS;
var mask = 1 << deployment.bit;
return bits === topBits && (this.version & mask) !== 0;
};
ChainEntry.prototype.__defineGetter__('rhash', function() { ChainEntry.prototype.__defineGetter__('rhash', function() {
return utils.revHex(this.hash); return utils.revHex(this.hash);
}); });

View File

@ -304,21 +304,23 @@ LowlevelUp.prototype.has = co(function* has(key) {
LowlevelUp.prototype.iterate = co(function* iterate(options) { LowlevelUp.prototype.iterate = co(function* iterate(options) {
var items = []; var items = [];
var iter, kv, result; var parse = options.parse;
var iter, result, data;
assert(typeof options.parse === 'function', 'Parse must be a function.'); assert(typeof parse === 'function', 'Parse must be a function.');
iter = this.iterator(options); iter = this.iterator(options);
for (;;) { for (;;) {
kv = yield iter.next(); result = yield iter.next();
if (!kv)
if (!result)
return items; return items;
result = options.parse(kv[0], kv[1]); data = parse(result.key, result.value);
if (result) if (data)
items.push(result); items.push(data);
} }
return items; return items;
@ -453,7 +455,7 @@ Iterator.prototype.next = function() {
return; return;
} }
resolve([key, value]); resolve(new KeyValue(key, value));
}); });
}); });
}; };
@ -473,6 +475,11 @@ Iterator.prototype.end = function end() {
* Helpers * Helpers
*/ */
function KeyValue(key, value) {
this.key = key;
this.value = value;
}
function isNotFound(err) { function isNotFound(err) {
if (!err) if (!err)
return false; return false;

View File

@ -115,7 +115,7 @@ Miner.prototype._init = function _init() {
if (bcoin.useWorkers) { if (bcoin.useWorkers) {
this.workerPool = new bcoin.workers({ this.workerPool = new bcoin.workers({
size: this.options.parallel ? 2 : 1, size: 1,
timeout: -1 timeout: -1
}); });
@ -268,7 +268,6 @@ Miner.prototype.createBlock = co(function* createBlock(tip) {
address: this.address, address: this.address,
coinbaseFlags: this.coinbaseFlags, coinbaseFlags: this.coinbaseFlags,
witness: this.chain.segwitActive, witness: this.chain.segwitActive,
parallel: this.options.parallel,
network: this.network network: this.network
}); });

View File

@ -339,6 +339,13 @@ Peer.prototype._bip151 = co(function* _bip151() {
} catch (err) { } catch (err) {
this.error(err, true); this.error(err, true);
} }
assert(this.bip151.completed);
if (this.bip151.handshake) {
this.logger.info('BIP151 handshake complete (%s).', this.hostname);
this.logger.info('Connection is encrypted (%s).', this.hostname);
}
}); });
/** /**
@ -347,17 +354,7 @@ Peer.prototype._bip151 = co(function* _bip151() {
*/ */
Peer.prototype._bip150 = co(function* _bip150() { Peer.prototype._bip150 = co(function* _bip150() {
if (!this.bip151) if (!this.bip151 || !this.bip150)
return;
assert(this.bip151.completed);
if (this.bip151.handshake) {
this.logger.info('BIP151 handshake complete (%s).', this.hostname);
this.logger.info('Connection is encrypted (%s).', this.hostname);
}
if (!this.bip150)
return; return;
assert(!this.bip150.completed); assert(!this.bip150.completed);
@ -2090,7 +2087,6 @@ Peer.prototype._handleCmpctBlock = co(function* _handleCmpctBlock(packet) {
return; return;
} }
// Sort of a lock too.
this.compactBlocks[hash] = block; this.compactBlocks[hash] = block;
result = block.fillMempool(this.mempool); result = block.fillMempool(this.mempool);

View File

@ -124,8 +124,7 @@ function Fullnode(options) {
mempool: this.mempool, mempool: this.mempool,
fees: this.fees, fees: this.fees,
address: this.options.payoutAddress, address: this.options.payoutAddress,
coinbaseFlags: this.options.coinbaseFlags, coinbaseFlags: this.options.coinbaseFlags
parallel: this.options.parallel
}); });
// Wallet database needs access to fees. // Wallet database needs access to fees.

View File

@ -844,6 +844,12 @@ MTX.prototype.template = function template(ring) {
var total = 0; var total = 0;
var i; var i;
if (Array.isArray(ring)) {
for (i = 0; i < ring.length; i++)
total += this.template(ring[i]);
return total;
}
for (i = 0; i < this.inputs.length; i++) { for (i = 0; i < this.inputs.length; i++) {
if (!ring.ownInput(this, i)) if (!ring.ownInput(this, i))
continue; continue;

View File

@ -592,13 +592,13 @@ Account.prototype.setDepth = co(function* setDepth(receiveDepth, changeDepth) {
} }
if (rings.length === 0) if (rings.length === 0)
return []; return;
yield this.saveAddress(rings); yield this.saveAddress(rings);
this.save(); this.save();
return [receive, change]; return receive;
}); });
/** /**

View File

@ -380,19 +380,19 @@ TXDB.prototype.getInfo = function getInfo(tx) {
* to orphan list. Stored by its required coin ID. * to orphan list. Stored by its required coin ID.
* @private * @private
* @param {Outpoint} prevout - Required coin hash & index. * @param {Outpoint} prevout - Required coin hash & index.
* @param {Buffer} spender - Spender input hash and index. * @param {Buffer} input - Spender input hash and index.
* @param {Function} callback - Returns [Error, Buffer]. * @param {Function} callback - Returns [Error, Buffer].
*/ */
TXDB.prototype.addOrphan = co(function* addOrphan(prevout, spender) { TXDB.prototype.addOrphan = co(function* addOrphan(prevout, input) {
var p = new BufferWriter();
var key = layout.o(prevout.hash, prevout.index); var key = layout.o(prevout.hash, prevout.index);
var data = yield this.get(key); var data = yield this.get(key);
var p = new BufferWriter();
if (data) if (data)
p.writeBytes(data); p.writeBytes(data);
p.writeBytes(spender); p.writeBytes(input);
this.put(key, p.render()); this.put(key, p.render());
}); });
@ -406,24 +406,24 @@ TXDB.prototype.addOrphan = co(function* addOrphan(prevout, spender) {
*/ */
TXDB.prototype.getOrphans = co(function* getOrphans(hash, index) { TXDB.prototype.getOrphans = co(function* getOrphans(hash, index) {
var key = layout.o(hash, index);
var data = yield this.get(key);
var items = []; var items = [];
var i, data, orphans, orphan, tx, p; var i, inputs, input, tx, p;
data = yield this.get(layout.o(hash, index));
if (!data) if (!data)
return; return;
p = new BufferReader(data); p = new BufferReader(data);
orphans = []; inputs = [];
while (p.left()) while (p.left())
orphans.push(bcoin.outpoint.fromRaw(p)); inputs.push(bcoin.outpoint.fromRaw(p));
for (i = 0; i < orphans.length; i++) { for (i = 0; i < inputs.length; i++) {
orphan = orphans[i]; input = inputs[i];
tx = yield this.getTX(orphan.hash); tx = yield this.getTX(input.hash);
items.push([orphan, tx]); items.push(new Orphan(input, tx));
} }
return items; return items;
@ -439,7 +439,7 @@ TXDB.prototype.getOrphans = co(function* getOrphans(hash, index) {
*/ */
TXDB.prototype.verify = co(function* verify(tx, info) { TXDB.prototype.verify = co(function* verify(tx, info) {
var i, input, prevout, address, coin, spent, rtx, rinfo, result; var i, input, prevout, address, coin, spent, conflict;
for (i = 0; i < tx.inputs.length; i++) { for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i]; input = tx.inputs[i];
@ -462,7 +462,7 @@ TXDB.prototype.verify = co(function* verify(tx, info) {
// Skip invalid transactions // Skip invalid transactions
if (this.options.verify) { if (this.options.verify) {
if (!tx.verifyInput(i)) if (!(yield tx.verifyInputAsync(i)))
return false; return false;
} }
@ -487,25 +487,23 @@ TXDB.prototype.verify = co(function* verify(tx, info) {
// Skip invalid transactions // Skip invalid transactions
if (this.options.verify) { if (this.options.verify) {
if (!tx.verifyInput(i)) if (!(yield tx.verifyInputAsync(i)))
return false; return false;
} }
this.logger.warning('Removing conflicting tx: %s.', this.logger.warning('Removing conflicting tx: %s.',
utils.revHex(spent.hash)); utils.revHex(spent.hash));
result = yield this.removeConflict(spent.hash, tx); // Remove the older double spender.
conflict = yield this.removeConflict(spent.hash, tx);
// Spender was not removed, the current // Spender was not removed, the current
// transaction is not elligible to be added. // transaction is not elligible to be added.
if (!result) if (!conflict)
return false; return false;
rtx = result[0];
rinfo = result[1];
// Emit the _removed_ transaction. // Emit the _removed_ transaction.
this.emit('conflict', rtx, rinfo); this.emit('conflict', conflict.tx, conflict.info);
} }
return true; return true;
@ -521,7 +519,7 @@ TXDB.prototype.verify = co(function* verify(tx, info) {
TXDB.prototype.resolveOrphans = co(function* resolveOrphans(tx, index) { TXDB.prototype.resolveOrphans = co(function* resolveOrphans(tx, index) {
var hash = tx.hash('hex'); var hash = tx.hash('hex');
var i, orphans, coin, item, input, orphan; var i, orphans, coin, input, orphan, key;
orphans = yield this.getOrphans(hash, index); orphans = yield this.getOrphans(hash, index);
@ -534,27 +532,28 @@ TXDB.prototype.resolveOrphans = co(function* resolveOrphans(tx, index) {
// Add input to orphan // Add input to orphan
for (i = 0; i < orphans.length; i++) { for (i = 0; i < orphans.length; i++) {
item = orphans[i]; orphan = orphans[i];
input = item[0]; input = orphan.input;
orphan = item[1]; tx = orphan.tx;
// Probably removed by some other means. // Probably removed by some other means.
if (!orphan) if (!tx)
continue; continue;
orphan.inputs[input.index].coin = coin; tx.inputs[input.index].coin = coin;
assert(orphan.inputs[input.index].prevout.hash === hash); assert(tx.inputs[input.index].prevout.hash === hash);
assert(orphan.inputs[input.index].prevout.index === index); assert(tx.inputs[input.index].prevout.index === index);
// Verify that input script is correct, if not - add // Verify that input script is correct, if not - add
// output to unspent and remove orphan from storage // output to unspent and remove orphan from storage
if (!this.options.verify || (yield orphan.verifyInputAsync(input.index))) { if (!this.options.verify || (yield tx.verifyInputAsync(input.index))) {
this.put(layout.d(input.hash, input.index), coin.toRaw()); key = layout.d(input.hash, input.index);
this.put(key, coin.toRaw());
return true; return true;
} }
yield this.lazyRemove(orphan); yield this.lazyRemove(tx);
} }
// Just going to be added again outside. // Just going to be added again outside.
@ -621,11 +620,14 @@ TXDB.prototype._add = co(function* add(tx, info) {
for (i = 0; i < info.accounts.length; i++) { for (i = 0; i < info.accounts.length; i++) {
account = info.accounts[i]; account = info.accounts[i];
this.put(layout.T(account, hash), DUMMY); this.put(layout.T(account, hash), DUMMY);
if (tx.ts === 0) if (tx.ts === 0)
this.put(layout.P(account, hash), DUMMY); this.put(layout.P(account, hash), DUMMY);
else else
this.put(layout.H(account, tx.height, hash), DUMMY); this.put(layout.H(account, tx.height, hash), DUMMY);
this.put(layout.M(account, tx.ps, hash), DUMMY); this.put(layout.M(account, tx.ps, hash), DUMMY);
} }
@ -646,7 +648,7 @@ TXDB.prototype._add = co(function* add(tx, info) {
key = prevout.hash + prevout.index; key = prevout.hash + prevout.index;
// s/[outpoint-key] -> [spender-hash]|[spender-input-index] // s[outpoint-key] -> [spender-hash]|[spender-input-index]
spender = bcoin.outpoint.fromTX(tx, i).toRaw(); spender = bcoin.outpoint.fromTX(tx, i).toRaw();
this.put(layout.s(prevout.hash, prevout.index), spender); this.put(layout.s(prevout.hash, prevout.index), spender);
@ -757,7 +759,7 @@ TXDB.prototype.removeConflict = co(function* removeConflict(hash, ref) {
info = yield this.removeRecursive(tx); info = yield this.removeRecursive(tx);
return [tx, info]; return new Conflict(tx, info);
}); });
/** /**
@ -774,6 +776,7 @@ TXDB.prototype.removeRecursive = co(function* removeRecursive(tx) {
for (i = 0; i < tx.outputs.length; i++) { for (i = 0; i < tx.outputs.length; i++) {
spent = yield this.isSpent(hash, i); spent = yield this.isSpent(hash, i);
if (!spent) if (!spent)
continue; continue;
@ -1019,11 +1022,14 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
for (i = 0; i < info.accounts.length; i++) { for (i = 0; i < info.accounts.length; i++) {
account = info.accounts[i]; account = info.accounts[i];
this.del(layout.T(account, hash)); this.del(layout.T(account, hash));
if (tx.ts === 0) if (tx.ts === 0)
this.del(layout.P(account, hash)); this.del(layout.P(account, hash));
else else
this.del(layout.H(account, tx.height, hash)); this.del(layout.H(account, tx.height, hash));
this.del(layout.M(account, tx.ps, hash)); this.del(layout.M(account, tx.ps, hash));
} }
@ -2092,6 +2098,16 @@ function sortCoins(coins) {
}); });
} }
function Conflict(tx, info) {
this.tx = tx;
this.info = info;
}
function Orphan(input, tx) {
this.input = input;
this.tx = tx;
}
/* /*
* Expose * Expose
*/ */

View File

@ -56,7 +56,6 @@ function Wallet(db, options) {
this.db = db; this.db = db;
this.network = db.network; this.network = db.network;
this.logger = db.logger; this.logger = db.logger;
this.workerPool = db.workerPool;
this.writeLock = new bcoin.locker(this); this.writeLock = new bcoin.locker(this);
this.fundLock = new bcoin.locker(this); this.fundLock = new bcoin.locker(this);
@ -1220,8 +1219,7 @@ Wallet.prototype._syncOutputDepth = co(function* syncOutputDepth(info) {
var receive = []; var receive = [];
var accounts = {}; var accounts = {};
var i, j, path, paths, account; var i, j, path, paths, account;
var receiveDepth, changeDepth; var receiveDepth, changeDepth, ring;
var ret, rcv, chng;
this.start(); this.start();
@ -1265,22 +1263,19 @@ Wallet.prototype._syncOutputDepth = co(function* syncOutputDepth(info) {
if (!account) if (!account)
continue; continue;
ret = yield account.setDepth(receiveDepth, changeDepth); ring = yield account.setDepth(receiveDepth, changeDepth);
rcv = ret[0]; if (ring)
chng = ret[1]; receive.push(ring);
if (rcv)
receive.push(rcv);
} }
yield this.commit();
if (receive.length > 0) { if (receive.length > 0) {
this.db.emit('address', this.id, receive); this.db.emit('address', this.id, receive);
this.emit('address', receive); this.emit('address', receive);
} }
yield this.commit();
return receive; return receive;
}); });
@ -1349,17 +1344,8 @@ Wallet.prototype.getRedeem = co(function* getRedeem(hash) {
*/ */
Wallet.prototype.template = co(function* template(tx) { Wallet.prototype.template = co(function* template(tx) {
var total = 0; var rings = yield this.deriveInputs(tx);
var i, rings, ring; return tx.template(rings);
rings = yield this.deriveInputs(tx);
for (i = 0; i < rings.length; i++) {
ring = rings[i];
total += tx.template(ring);
}
return total;
}); });
/** /**
@ -1372,7 +1358,7 @@ Wallet.prototype.template = co(function* template(tx) {
*/ */
Wallet.prototype.sign = co(function* sign(tx, options) { Wallet.prototype.sign = co(function* sign(tx, options) {
var master, rings; var rings;
if (!options) if (!options)
options = {}; options = {};
@ -1380,36 +1366,13 @@ Wallet.prototype.sign = co(function* sign(tx, options) {
if (typeof options === 'string' || Buffer.isBuffer(options)) if (typeof options === 'string' || Buffer.isBuffer(options))
options = { passphrase: options }; options = { passphrase: options };
master = yield this.unlock(options.passphrase, options.timeout); yield this.unlock(options.passphrase, options.timeout);
rings = yield this.deriveInputs(tx); rings = yield this.deriveInputs(tx);
return yield this.signAsync(rings, tx); return yield tx.signAsync(rings);
}); });
/**
* Sign a transaction asynchronously.
* @param {KeyRing[]} rings
* @param {MTX} tx
* @param {Function} callback - Returns [Error, Number] (total number
* of inputs scripts built and signed).
*/
Wallet.prototype.signAsync = function signAsync(rings, tx) {
var result;
if (!this.workerPool) {
try {
result = tx.sign(rings);
} catch (e) {
return Promise.reject(e);
}
return Promise.resolve(result);
}
return this.workerPool.sign(tx, rings, null);
};
/** /**
* Fill transaction with coins (accesses db). * Fill transaction with coins (accesses db).
* @param {TX} tx * @param {TX} tx

View File

@ -128,7 +128,6 @@ function WalletDB(options) {
this.logger = options.logger || bcoin.defaultLogger; this.logger = options.logger || bcoin.defaultLogger;
this.batches = {}; this.batches = {};
this.wallets = {}; this.wallets = {};
this.workerPool = null;
this.tip = this.network.genesis.hash; this.tip = this.network.genesis.hash;
this.height = 0; this.height = 0;
@ -163,9 +162,6 @@ function WalletDB(options) {
bufferKeys: !utils.isBrowser bufferKeys: !utils.isBrowser
}); });
if (bcoin.useWorkers)
this.workerPool = new bcoin.workers();
this._init(); this._init();
} }
@ -184,13 +180,7 @@ WalletDB.layout = layout;
*/ */
WalletDB.prototype._init = function _init() { WalletDB.prototype._init = function _init() {
var self = this; ;
if (bcoin.useWorkers) {
this.workerPool.on('error', function(err) {
self.emit('error', err);
});
}
}; };
/** /**
@ -249,7 +239,7 @@ WalletDB.prototype.backup = function backup(path) {
*/ */
WalletDB.prototype.getDepth = co(function* getDepth() { WalletDB.prototype.getDepth = co(function* getDepth() {
var kv, iter, depth; var result, iter, depth;
// This may seem like a strange way to do // This may seem like a strange way to do
// this, but updating a global state when // this, but updating a global state when
@ -266,14 +256,14 @@ WalletDB.prototype.getDepth = co(function* getDepth() {
reverse: true reverse: true
}); });
kv = yield iter.next(); result = yield iter.next();
if (!kv) if (!result)
return 1; return 1;
yield iter.end(); yield iter.end();
depth = layout.ww(kv[0]); depth = layout.ww(result.key);
return depth + 1; return depth + 1;
}); });
@ -1546,11 +1536,15 @@ PathInfo.prototype.fromTX = function fromTX(tx, table) {
for (i = 0; i < hashes.length; i++) { for (i = 0; i < hashes.length; i++) {
hash = hashes[i]; hash = hashes[i];
paths = table[hash]; paths = table[hash];
for (j = 0; j < paths.length; j++) { for (j = 0; j < paths.length; j++) {
path = paths[j]; path = paths[j];
if (path.wid !== this.wid) if (path.wid !== this.wid)
continue; continue;
this.pathMap[hash] = path; this.pathMap[hash] = path;
if (!uniq[path.account]) { if (!uniq[path.account]) {
uniq[path.account] = true; uniq[path.account] = true;
this.accounts.push(path.account); this.accounts.push(path.account);
@ -1563,10 +1557,13 @@ PathInfo.prototype.fromTX = function fromTX(tx, table) {
for (i = 0; i < hashes.length; i++) { for (i = 0; i < hashes.length; i++) {
hash = hashes[i]; hash = hashes[i];
paths = table[hash]; paths = table[hash];
for (j = 0; j < paths.length; j++) { for (j = 0; j < paths.length; j++) {
path = paths[j]; path = paths[j];
if (path.wid !== this.wid) if (path.wid !== this.wid)
continue; continue;
this.paths.push(path); this.paths.push(path);
} }
} }