wallet: fixes for wallet server.

This commit is contained in:
Christopher Jeffrey 2017-10-26 15:35:23 -07:00
parent 877cecbedc
commit 749d4edc11
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
11 changed files with 108 additions and 70 deletions

10
bin/cli
View File

@ -430,7 +430,7 @@ CLI.prototype.retoken = async function retoken() {
CLI.prototype.rescan = async function rescan() {
const height = this.config.uint(0);
await this.client.rescan(height);
await this.wallet.rescan(height);
this.log('Rescanning...');
};
@ -658,6 +658,9 @@ CLI.prototype.handleWallet = async function handleWallet() {
case 'resend':
await this.resendWallet();
break;
case 'rescan':
await this.rescan();
break;
default:
this.log('Unrecognized command.');
this.log('Commands:');
@ -692,6 +695,7 @@ CLI.prototype.handleWallet = async function handleWallet() {
this.log(' $ lock: Lock wallet.');
this.log(' $ unlock [passphrase] [timeout?]: Unlock wallet.');
this.log(' $ resend: Resend pending transactions.');
this.log(' $ rescan [height]: Rescan for transactions.');
this.log('Other Options:');
this.log(' --passphrase [passphrase]: For signing & account creation.');
this.log(' --account [account-name]: Account name.');
@ -734,9 +738,6 @@ CLI.prototype.handleNode = async function handleNode() {
case 'block':
await this.getBlock();
break;
case 'rescan':
await this.rescan();
break;
case 'reset':
await this.reset();
break;
@ -760,7 +761,6 @@ CLI.prototype.handleNode = async function handleNode() {
this.log(' $ tx [hash/address]: View transactions.');
this.log(' $ coin [hash+index/address]: View coins.');
this.log(' $ block [hash/height]: View block.');
this.log(' $ rescan [height]: Rescan for transactions.');
this.log(' $ reset [height/hash]: Reset chain to desired block.');
this.log(' $ resend: Resend pending transactions.');
this.log(' $ backup [path]: Backup the wallet db.');

View File

@ -905,7 +905,7 @@ Chain.prototype.reorganize = async function reorganize(competitor) {
competitor.height
);
await this.fire('reorganize', tip, competitor);
await this.call('reorganize', tip, competitor);
};
/**
@ -942,7 +942,7 @@ Chain.prototype.reorganizeSPV = async function reorganizeSPV(competitor) {
for (const entry of disconnect) {
const headers = entry.toHeaders();
const view = new CoinView();
await this.fire('disconnect', entry, headers, view);
await this.call('disconnect', entry, headers, view);
}
this.logger.warning(
@ -957,7 +957,7 @@ Chain.prototype.reorganizeSPV = async function reorganizeSPV(competitor) {
'Chain replay from height %d necessary.',
fork.height);
await this.fire('reorganize', tip, competitor);
await this.call('reorganize', tip, competitor);
};
/**
@ -985,7 +985,7 @@ Chain.prototype.disconnect = async function disconnect(entry) {
this.emit('tip', prev);
await this.fire('disconnect', entry, block, view);
await this.call('disconnect', entry, block, view);
};
/**
@ -1035,7 +1035,7 @@ Chain.prototype.reconnect = async function reconnect(entry) {
this.emit('tip', entry);
this.emit('reconnect', entry, block);
await this.fire('connect', entry, block, view);
await this.call('connect', entry, block, view);
};
/**
@ -1103,7 +1103,7 @@ Chain.prototype.setBestChain = async function setBestChain(entry, block, prev, f
this.emit('tip', entry);
this.emit('block', block, entry);
await this.fire('connect', entry, block, view);
await this.call('connect', entry, block, view);
};
/**
@ -1198,7 +1198,7 @@ Chain.prototype._reset = async function _reset(block, silent) {
this.emit('tip', tip);
if (!silent)
await this.fire('reset', tip);
await this.call('reset', tip);
// Reset the orphan map completely. There may
// have been some orphans on a forked chain we

View File

@ -1307,7 +1307,7 @@ ChainDB.prototype.scan = async function scan(start, filter, iter) {
const block = await this.getBlock(entry.hash);
const txs = [];
total++;
total += 1;
if (!block) {
if (!this.options.spv && !this.options.prune)

View File

@ -498,7 +498,7 @@ class HTTP extends Server {
const tx = TX.fromRaw(data);
this.node.send(tx);
this.node.relay(tx);
return null;
});
@ -655,7 +655,7 @@ class HTTP extends Server {
for (const tx of txs)
raw.push(tx.toRaw());
return socket.fire('block rescan', block, raw);
return socket.call('block rescan', block, raw);
});
return null;
}

View File

@ -209,6 +209,37 @@ AsyncEmitter.prototype.listenerCount = function listenerCount(type) {
return listeners.length;
};
/**
* Add a listener.
* @param {String} type
* @param {Function} handler
*/
AsyncEmitter.prototype.listen = function listen(type, handler) {
return this.on(type, handler);
};
/**
* Add a listener.
* @param {String} type
* @param {Function} handler
*/
AsyncEmitter.prototype.hook = function hook(type, handler) {
return this.on(type, handler);
};
/**
* Emit event.
* @param {String} type
* @param {...Object} args
* @returns {Promise}
*/
AsyncEmitter.prototype.fire = function fire() {
return this.emit.apply(this, arguments);
};
/**
* Emit an event synchronously.
* @method
@ -280,7 +311,7 @@ AsyncEmitter.prototype.emit = function emit(type) {
* @returns {Promise}
*/
AsyncEmitter.prototype.fire = async function fire(type) {
AsyncEmitter.prototype.call = async function call(type) {
assert(typeof type === 'string', '`type` must be a string.');
const listeners = this._events[type];
@ -343,15 +374,15 @@ AsyncEmitter.prototype.fire = async function fire(type) {
* @returns {Promise}
*/
AsyncEmitter.prototype.tryFire = async function tryFire(type) {
AsyncEmitter.prototype.tryCall = async function tryCall(type) {
try {
await this.fire.apply(this, arguments);
await this.call.apply(this, arguments);
} catch (e) {
if (type === 'error')
return;
try {
await this.fire('error', e);
await this.call('error', e);
} catch (e) {
;
}

View File

@ -61,7 +61,7 @@ AsyncObject.prototype.__open = async function __open() {
if (this.loaded)
return;
await this.fire('preopen');
await this.call('preopen');
this.loading = true;
@ -76,7 +76,7 @@ AsyncObject.prototype.__open = async function __open() {
this.loading = false;
this.loaded = true;
await this.fire('open');
await this.call('open');
};
/**
@ -105,7 +105,7 @@ AsyncObject.prototype.__close = async function __close() {
if (!this.loaded)
return;
await this.fire('preclose');
await this.call('preclose');
this.closing = true;
@ -120,7 +120,7 @@ AsyncObject.prototype.__close = async function __close() {
this.closing = false;
this.loaded = false;
await this.fire('close');
await this.call('close');
};
/**
@ -151,6 +151,27 @@ AsyncObject.prototype._close = function _close(callback) {
throw new Error('Abstract method.');
};
/**
* Add a listener.
* @param {String} type
* @param {Function} handler
*/
AsyncObject.prototype.listen = function listen(type, handler) {
return this.on(type, handler);
};
/**
* Emit event.
* @param {String} type
* @param {...Object} args
* @returns {Promise}
*/
AsyncObject.prototype.fire = function fire() {
return this.emit.apply(this, arguments);
};
/**
* Add a hook listener.
* @param {String} type
@ -174,8 +195,8 @@ AsyncObject.prototype.hook = function hook(type, handler) {
* @returns {Promise}
*/
AsyncObject.prototype.fire = async function fire() {
await this.fireHook.apply(this, arguments);
AsyncObject.prototype.call = async function call() {
await this.callHook.apply(this, arguments);
this.emit.apply(this, arguments);
};
@ -188,7 +209,7 @@ AsyncObject.prototype.fire = async function fire() {
* @returns {Promise}
*/
AsyncObject.prototype.fireHook = async function fireHook(type) {
AsyncObject.prototype.callHook = async function callHook(type) {
assert(typeof type === 'string', '`type` must be a string.');
const listeners = this._hooks[type];

View File

@ -335,6 +335,7 @@ Bloom.prototype.toRaw = function toRaw() {
Bloom.prototype.fromReader = function fromReader(br) {
this.filter = br.readVarBytes();
this.size = this.filter.length * 8;
this.n = br.readU32();
this.tweak = br.readU32();
this.update = br.readU8();

View File

@ -21,24 +21,24 @@ class WalletClient extends NodeClient {
async open() {
await super.open();
this.listen('block connect', (entry, txs) => {
this.emit('block connect', ...parseBlock(entry, txs));
this.parse('block connect', (entry, txs) => {
return parseBlock(entry, txs);
});
this.listen('block disconnect', (entry) => {
this.emit('block disconnect', parseEntry(entry));
this.parse('block disconnect', (entry) => {
return parseEntry(entry);
});
this.listen('block rescan', (entry, txs) => {
this.emit('block rescan', ...parseBlock(entry, txs));
this.parse('block rescan', (entry, txs) => {
return parseBlock(entry, txs);
});
this.listen('chain reset', (tip) => {
this.emit('chain reset', parseEntry(tip));
this.parse('chain reset', (tip) => {
return parseEntry(tip);
});
this.listen('tx', (tx) => {
this.emit('tx', TX.fromRaw(tx));
this.parse('tx', (tx) => {
return TX.fromRaw(tx);
});
}

View File

@ -24,7 +24,7 @@ function NodeClient(node) {
this.node = node;
this.network = node.network;
this.filter = null;
this.listen = false;
this.listening = false;
this._init();
}
@ -38,28 +38,28 @@ Object.setPrototypeOf(NodeClient.prototype, AsyncObject.prototype);
NodeClient.prototype._init = function _init() {
this.node.on('connect', (entry, block) => {
if (!this.listen)
if (!this.listening)
return;
this.emit('block connect', entry, block.txs);
});
this.node.on('disconnect', (entry, block) => {
if (!this.listen)
if (!this.listening)
return;
this.emit('block disconnect', entry);
});
this.node.on('tx', (tx) => {
if (!this.listen)
if (!this.listening)
return;
this.emit('tx', tx);
});
this.node.on('reset', (tip) => {
if (!this.listen)
if (!this.listening)
return;
this.emit('chain reset', tip);
@ -72,7 +72,7 @@ NodeClient.prototype._init = function _init() {
*/
NodeClient.prototype._open = function _open(options) {
this.listen = true;
this.listening = true;
this.emit('open');
return Promise.resolve();
};
@ -83,7 +83,7 @@ NodeClient.prototype._open = function _open(options) {
*/
NodeClient.prototype._close = function _close() {
this.listen = false;
this.listening = false;
this.emit('close');
return Promise.resolve();
};
@ -193,7 +193,7 @@ NodeClient.prototype.getHashes = async function getHashes(start = -1, end = -1)
NodeClient.prototype.rescan = function rescan(start) {
return this.node.chain.scan(start, this.filter, (entry, txs) => {
return this.fire('block rescan', entry, txs);
return this.call('block rescan', entry, txs);
});
};

View File

@ -107,7 +107,7 @@ WalletNode.prototype._open = async function _open(callback) {
await this.http.open();
this.logger.info('Node is loaded.');
this.logger.info('Wallet node is loaded.');
};
/**

View File

@ -133,9 +133,11 @@ WalletDB.prototype._open = async function _open() {
id: 'primary'
});
const addr = await wallet.receiveAddress();
this.logger.info(
'Loaded primary wallet (id=%s, wid=%d, address=%s)',
wallet.id, wallet.wid, await wallet.receiveAddress());
wallet.id, wallet.wid, addr.toString(this.network));
this.primary = wallet;
};
@ -215,7 +217,7 @@ WalletDB.prototype.bind = function bind() {
}
});
this.client.on('block connect', async (entry, txs) => {
this.client.listen('block connect', async (entry, txs) => {
try {
await this.addBlock(entry, txs);
} catch (e) {
@ -223,7 +225,7 @@ WalletDB.prototype.bind = function bind() {
}
});
this.client.on('block disconnect', async (entry) => {
this.client.listen('block disconnect', async (entry) => {
try {
await this.removeBlock(entry);
} catch (e) {
@ -231,7 +233,7 @@ WalletDB.prototype.bind = function bind() {
}
});
this.client.on('block rescan', async (entry, txs) => {
this.client.hook('block rescan', async (entry, txs) => {
try {
await this.rescanBlock(entry, txs);
} catch (e) {
@ -239,7 +241,7 @@ WalletDB.prototype.bind = function bind() {
}
});
this.client.on('tx', async (tx) => {
this.client.listen('tx', async (tx) => {
try {
await this.addTX(tx);
} catch (e) {
@ -247,7 +249,7 @@ WalletDB.prototype.bind = function bind() {
}
});
this.client.on('chain reset', async (tip) => {
this.client.listen('chain reset', async (tip) => {
try {
await this.resetChain(tip);
} catch (e) {
@ -1891,30 +1893,13 @@ WalletDB.prototype._removeBlock = async function _removeBlock(entry) {
*/
WalletDB.prototype.rescanBlock = async function rescanBlock(entry, txs) {
const unlock = await this.scanLock.lock();
try {
return await this._rescanBlock(entry, txs);
} finally {
unlock();
}
};
/**
* Rescan a block.
* @private
* @param {ChainEntry} entry
* @param {TX[]} txs
* @returns {Promise}
*/
WalletDB.prototype._rescanBlock = async function _rescanBlock(entry, txs) {
if (!this.rescanning) {
this.logger.warning('Unsolicited rescan block: %s.', entry.height);
this.logger.warning('Unsolicited rescan block: %d.', entry.height);
return;
}
if (entry.height > this.state.height + 1) {
this.logger.warning('Unsolicited rescan block: %s.', entry.height);
this.logger.warning('Rescan block too high: %d.', entry.height);
return;
}