bcoin: classify everything else.

This commit is contained in:
Christopher Jeffrey 2017-11-16 20:32:26 -08:00
parent bad24a6f31
commit 73664efcd0
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
5 changed files with 1607 additions and 1603 deletions

206
bin/cli
View File

@ -23,7 +23,8 @@ const ANTIREPLAY = ''
+ '6a2e426974636f696e3a204120506565722d746f2d5065657' + '6a2e426974636f696e3a204120506565722d746f2d5065657'
+ '220456c656374726f6e696320436173682053797374656d'; + '220456c656374726f6e696320436173682053797374656d';
function CLI() { class CLI {
constructor() {
this.config = new Config('bcoin', { this.config = new Config('bcoin', {
suffix: 'network', suffix: 'network',
fallback: 'main', fallback: 'main',
@ -48,25 +49,25 @@ function CLI() {
this.argv = this.config.argv; this.argv = this.config.argv;
this.client = null; this.client = null;
this.wallet = null; this.wallet = null;
} }
CLI.prototype.log = function log(json) { log(json) {
if (typeof json === 'string') if (typeof json === 'string')
return console.log.apply(console, arguments); return console.log.apply(console, arguments);
return console.log(JSON.stringify(json, null, 2)); return console.log(JSON.stringify(json, null, 2));
}; }
CLI.prototype.getInfo = async function getInfo() { async getInfo() {
const info = await this.client.getInfo(); const info = await this.client.getInfo();
this.log(info); this.log(info);
}; }
CLI.prototype.getWallets = async function getWallets() { async getWallets() {
const wallets = await this.client.getWallets(); const wallets = await this.client.getWallets();
this.log(wallets); this.log(wallets);
}; }
CLI.prototype.createWallet = async function createWallet() { async createWallet() {
const options = { const options = {
id: this.config.str([0, 'id']), id: this.config.str([0, 'id']),
type: this.config.str('type'), type: this.config.str('type'),
@ -83,22 +84,22 @@ CLI.prototype.createWallet = async function createWallet() {
const wallet = await this.client.createWallet(options); const wallet = await this.client.createWallet(options);
this.log(wallet); this.log(wallet);
}; }
CLI.prototype.getMaster = async function getMaster() { async getMaster() {
const master = await this.wallet.getMaster(); const master = await this.wallet.getMaster();
this.log(master); this.log(master);
}; }
CLI.prototype.getKey = async function getKey() { async getKey() {
const address = this.config.str(0); const address = this.config.str(0);
const key = await this.wallet.getKey(address); const key = await this.wallet.getKey(address);
this.log(key); this.log(key);
}; }
CLI.prototype.getWIF = async function getWIF() { async getWIF() {
const address = this.config.str(0); const address = this.config.str(0);
const passphrase = this.config.str('passphrase'); const passphrase = this.config.str('passphrase');
const key = await this.wallet.getWIF(address, passphrase); const key = await this.wallet.getWIF(address, passphrase);
@ -109,27 +110,27 @@ CLI.prototype.getWIF = async function getWIF() {
} }
this.log(key.privateKey); this.log(key.privateKey);
}; }
CLI.prototype.addSharedKey = async function addSharedKey() { async addSharedKey() {
const key = this.config.str(0); const key = this.config.str(0);
const account = this.config.str('account'); const account = this.config.str('account');
await this.wallet.addSharedKey(account, key); await this.wallet.addSharedKey(account, key);
this.log('Added key.'); this.log('Added key.');
}; }
CLI.prototype.removeSharedKey = async function removeSharedKey() { async removeSharedKey() {
const key = this.config.str(0); const key = this.config.str(0);
const account = this.config.str('account'); const account = this.config.str('account');
await this.wallet.removeSharedKey(account, key); await this.wallet.removeSharedKey(account, key);
this.log('Removed key.'); this.log('Removed key.');
}; }
CLI.prototype.getSharedKeys = async function getSharedKeys() { async getSharedKeys() {
const acct = this.config.str([0, 'account']); const acct = this.config.str([0, 'account']);
const account = await this.wallet.getAccount(acct); const account = await this.wallet.getAccount(acct);
@ -139,16 +140,16 @@ CLI.prototype.getSharedKeys = async function getSharedKeys() {
} }
this.log(account.keys); this.log(account.keys);
}; }
CLI.prototype.getAccount = async function getAccount() { async getAccount() {
const acct = this.config.str([0, 'account']); const acct = this.config.str([0, 'account']);
const account = await this.wallet.getAccount(acct); const account = await this.wallet.getAccount(acct);
this.log(account); this.log(account);
}; }
CLI.prototype.createAccount = async function createAccount() { async createAccount() {
const name = this.config.str([0, 'name']); const name = this.config.str([0, 'name']);
const options = { const options = {
@ -162,40 +163,40 @@ CLI.prototype.createAccount = async function createAccount() {
const account = await this.wallet.createAccount(name, options); const account = await this.wallet.createAccount(name, options);
this.log(account); this.log(account);
}; }
CLI.prototype.createAddress = async function createAddress() { async createAddress() {
const account = this.config.str([0, 'account']); const account = this.config.str([0, 'account']);
const addr = await this.wallet.createAddress(account); const addr = await this.wallet.createAddress(account);
this.log(addr); this.log(addr);
}; }
CLI.prototype.createChange = async function createChange() { async createChange() {
const account = this.config.str([0, 'account']); const account = this.config.str([0, 'account']);
const addr = await this.wallet.createChange(account); const addr = await this.wallet.createChange(account);
this.log(addr); this.log(addr);
}; }
CLI.prototype.createNested = async function createNested() { async createNested() {
const account = this.config.str([0, 'account']); const account = this.config.str([0, 'account']);
const addr = await this.wallet.createNested(account); const addr = await this.wallet.createNested(account);
this.log(addr); this.log(addr);
}; }
CLI.prototype.getAccounts = async function getAccounts() { async getAccounts() {
const accounts = await this.wallet.getAccounts(); const accounts = await this.wallet.getAccounts();
this.log(accounts); this.log(accounts);
}; }
CLI.prototype.getWallet = async function getWallet() { async getWallet() {
const info = await this.wallet.getInfo(); const info = await this.wallet.getInfo();
this.log(info); this.log(info);
}; }
CLI.prototype.getTX = async function getTX() { async getTX() {
const hash = this.config.str(0, ''); const hash = this.config.str(0, '');
if (hash.length !== 64) { if (hash.length !== 64) {
@ -212,9 +213,9 @@ CLI.prototype.getTX = async function getTX() {
} }
this.log(tx); this.log(tx);
}; }
CLI.prototype.getBlock = async function getBlock() { async getBlock() {
let hash = this.config.str(0, ''); let hash = this.config.str(0, '');
if (hash.length !== 64) if (hash.length !== 64)
@ -228,9 +229,9 @@ CLI.prototype.getBlock = async function getBlock() {
} }
this.log(block); this.log(block);
}; }
CLI.prototype.getCoin = async function getCoin() { async getCoin() {
const hash = this.config.str(0, ''); const hash = this.config.str(0, '');
const index = this.config.uint(1); const index = this.config.uint(1);
@ -248,30 +249,30 @@ CLI.prototype.getCoin = async function getCoin() {
} }
this.log(coin); this.log(coin);
}; }
CLI.prototype.getWalletHistory = async function getWalletHistory() { async getWalletHistory() {
const account = this.config.str('account'); const account = this.config.str('account');
const txs = await this.wallet.getHistory(account); const txs = await this.wallet.getHistory(account);
this.log(txs); this.log(txs);
}; }
CLI.prototype.getWalletPending = async function getWalletPending() { async getWalletPending() {
const account = this.config.str('account'); const account = this.config.str('account');
const txs = await this.wallet.getPending(account); const txs = await this.wallet.getPending(account);
this.log(txs); this.log(txs);
}; }
CLI.prototype.getWalletCoins = async function getWalletCoins() { async getWalletCoins() {
const account = this.config.str('account'); const account = this.config.str('account');
const coins = await this.wallet.getCoins(account); const coins = await this.wallet.getCoins(account);
this.log(coins); this.log(coins);
}; }
CLI.prototype.listenWallet = async function listenWallet() { async listenWallet() {
await this.wallet.open(); await this.wallet.open();
this.wallet.on('tx', (details) => { this.wallet.on('tx', (details) => {
@ -305,22 +306,22 @@ CLI.prototype.listenWallet = async function listenWallet() {
}); });
return await this.wallet.onDisconnect(); return await this.wallet.onDisconnect();
}; }
CLI.prototype.getBalance = async function getBalance() { async getBalance() {
const account = this.config.str('account'); const account = this.config.str('account');
const balance = await this.wallet.getBalance(account); const balance = await this.wallet.getBalance(account);
this.log(balance); this.log(balance);
}; }
CLI.prototype.getMempool = async function getMempool() { async getMempool() {
const txs = await this.client.getMempool(); const txs = await this.client.getMempool();
this.log(txs); this.log(txs);
}; }
CLI.prototype.sendTX = async function sendTX() { async sendTX() {
const outputs = []; const outputs = [];
if (this.config.has('script')) { if (this.config.has('script')) {
@ -354,9 +355,9 @@ CLI.prototype.sendTX = async function sendTX() {
const tx = await this.wallet.send(options); const tx = await this.wallet.send(options);
this.log(tx); this.log(tx);
}; }
CLI.prototype.createTX = async function createTX() { async createTX() {
let output; let output;
if (this.config.has('script')) { if (this.config.has('script')) {
@ -383,74 +384,74 @@ CLI.prototype.createTX = async function createTX() {
const tx = await this.wallet.createTX(options); const tx = await this.wallet.createTX(options);
this.log(tx); this.log(tx);
}; }
CLI.prototype.signTX = async function signTX() { async signTX() {
const passphrase = this.config.str('passphrase'); const passphrase = this.config.str('passphrase');
const raw = this.config.str([0, 'tx']); const raw = this.config.str([0, 'tx']);
const tx = await this.wallet.sign(raw, { passphrase }); const tx = await this.wallet.sign(raw, { passphrase });
this.log(tx); this.log(tx);
}; }
CLI.prototype.zapWallet = async function zapWallet() { async zapWallet() {
const age = this.config.uint([0, 'age'], 72 * 60 * 60); const age = this.config.uint([0, 'age'], 72 * 60 * 60);
await this.wallet.zap(this.config.str('account'), age); await this.wallet.zap(this.config.str('account'), age);
this.log('Zapped!'); this.log('Zapped!');
}; }
CLI.prototype.broadcast = async function broadcast() { async broadcast() {
const raw = this.config.str([0, 'tx']); const raw = this.config.str([0, 'tx']);
const tx = await this.client.broadcast(raw); const tx = await this.client.broadcast(raw);
this.log('Broadcasted:'); this.log('Broadcasted:');
this.log(tx); this.log(tx);
}; }
CLI.prototype.viewTX = async function viewTX() { async viewTX() {
const raw = this.config.str([0, 'tx']); const raw = this.config.str([0, 'tx']);
const tx = await this.wallet.fill(raw); const tx = await this.wallet.fill(raw);
this.log(tx); this.log(tx);
}; }
CLI.prototype.getDetails = async function getDetails() { async getDetails() {
const hash = this.config.str(0); const hash = this.config.str(0);
const details = await this.wallet.getTX(hash); const details = await this.wallet.getTX(hash);
this.log(details); this.log(details);
}; }
CLI.prototype.getWalletBlocks = async function getWalletBlocks() { async getWalletBlocks() {
const blocks = await this.wallet.getBlocks(); const blocks = await this.wallet.getBlocks();
this.log(blocks); this.log(blocks);
}; }
CLI.prototype.getWalletBlock = async function getWalletBlock() { async getWalletBlock() {
const height = this.config.uint(0); const height = this.config.uint(0);
const block = await this.wallet.getBlock(height); const block = await this.wallet.getBlock(height);
this.log(block); this.log(block);
}; }
CLI.prototype.retoken = async function retoken() { async retoken() {
const passphrase = this.config.str('passphrase'); const passphrase = this.config.str('passphrase');
const result = await this.wallet.retoken(passphrase); const result = await this.wallet.retoken(passphrase);
this.log(result); this.log(result);
}; }
CLI.prototype.rescan = async function rescan() { async rescan() {
const height = this.config.uint(0); const height = this.config.uint(0);
await this.wallet.rescan(height); await this.wallet.rescan(height);
this.log('Rescanning...'); this.log('Rescanning...');
}; }
CLI.prototype.reset = async function reset() { async reset() {
let hash = this.config.str(0); let hash = this.config.str(0);
if (hash.length !== 64) if (hash.length !== 64)
@ -459,29 +460,29 @@ CLI.prototype.reset = async function reset() {
await this.client.reset(hash); await this.client.reset(hash);
this.log('Chain has been reset.'); this.log('Chain has been reset.');
}; }
CLI.prototype.resend = async function resend() { async resend() {
await this.client.resend(); await this.client.resend();
this.log('Resending...'); this.log('Resending...');
}; }
CLI.prototype.resendWallet = async function resendWallet() { async resendWallet() {
await this.wallet.resend(); await this.wallet.resend();
this.log('Resending...'); this.log('Resending...');
}; }
CLI.prototype.backup = async function backup() { async backup() {
const path = this.config.str(0); const path = this.config.str(0);
await this.client.backup(path); await this.client.backup(path);
this.log('Backup complete.'); this.log('Backup complete.');
}; }
CLI.prototype.importKey = async function importKey() { async importKey() {
const key = this.config.str(0); const key = this.config.str(0);
const account = this.config.str('account'); const account = this.config.str('account');
const passphrase = this.config.str('passphrase'); const passphrase = this.config.str('passphrase');
@ -498,33 +499,33 @@ CLI.prototype.importKey = async function importKey() {
await this.wallet.importPrivate(account, key, passphrase); await this.wallet.importPrivate(account, key, passphrase);
this.log('Imported private key.'); this.log('Imported private key.');
}; }
CLI.prototype.importAddress = async function importAddress() { async importAddress() {
const address = this.config.str(0); const address = this.config.str(0);
const account = this.config.str('account'); const account = this.config.str('account');
await this.wallet.importAddress(account, address); await this.wallet.importAddress(account, address);
this.log('Imported address.'); this.log('Imported address.');
}; }
CLI.prototype.lock = async function lock() { async lock() {
await this.wallet.lock(); await this.wallet.lock();
this.log('Locked.'); this.log('Locked.');
}; }
CLI.prototype.unlock = async function unlock() { async unlock() {
const passphrase = this.config.str(0); const passphrase = this.config.str(0);
const timeout = this.config.uint(1); const timeout = this.config.uint(1);
await this.wallet.unlock(passphrase, timeout); await this.wallet.unlock(passphrase, timeout);
this.log('Unlocked.'); this.log('Unlocked.');
}; }
CLI.prototype.rpc = async function rpc() { async rpc() {
const method = this.argv.shift(); const method = this.argv.shift();
const params = []; const params = [];
@ -550,9 +551,9 @@ CLI.prototype.rpc = async function rpc() {
} }
this.log(result); this.log(result);
}; }
CLI.prototype.handleWallet = async function handleWallet() { async handleWallet() {
const network = this.config.str('network', 'main'); const network = this.config.str('network', 'main');
this.wallet = new WalletClient({ this.wallet = new WalletClient({
@ -719,9 +720,9 @@ CLI.prototype.handleWallet = async function handleWallet() {
this.log(' --account [account-name]: Account name.'); this.log(' --account [account-name]: Account name.');
break; break;
} }
}; }
CLI.prototype.handleNode = async function handleNode() { async handleNode() {
const network = this.config.str('network', 'main'); const network = this.config.str('network', 'main');
this.client = new NodeClient({ this.client = new NodeClient({
@ -788,9 +789,9 @@ CLI.prototype.handleNode = async function handleNode() {
this.log(' $ rpc [command] [args]: Execute RPC command.'); this.log(' $ rpc [command] [args]: Execute RPC command.');
break; break;
} }
}; }
CLI.prototype.open = async function open() { async open() {
switch (this.argv[0]) { switch (this.argv[0]) {
case 'w': case 'w':
case 'wallet': case 'wallet':
@ -806,15 +807,16 @@ CLI.prototype.open = async function open() {
await this.handleNode(); await this.handleNode();
break; break;
} }
}; }
CLI.prototype.destroy = async function destroy() { async destroy() {
if (this.wallet && this.wallet.opened) if (this.wallet && this.wallet.opened)
await this.wallet.close(); await this.wallet.close();
if (this.client && this.client.opened) if (this.client && this.client.opened)
await this.client.close(); await this.client.close();
}; }
}
(async () => { (async () => {
const cli = new CLI(); const cli = new CLI();

View File

@ -12,11 +12,9 @@ const bsock = require('bsock');
const hash256 = require('bcrypto/lib/hash256'); const hash256 = require('bcrypto/lib/hash256');
const bio = require('bufio'); const bio = require('bufio');
function ProxySocket(uri) { class ProxySocket extends EventEmitter {
if (!(this instanceof ProxySocket)) constructor(uri) {
return new ProxySocket(uri); super();
EventEmitter.call(this);
this.info = null; this.info = null;
@ -33,11 +31,9 @@ function ProxySocket(uri) {
this.closed = false; this.closed = false;
this.init(); this.init();
} }
Object.setPrototypeOf(ProxySocket.prototype, EventEmitter.prototype); init() {
ProxySocket.prototype.init = function init() {
this.socket.bind('info', (info) => { this.socket.bind('info', (info) => {
if (this.closed) if (this.closed)
return; return;
@ -97,9 +93,9 @@ ProxySocket.prototype.init = function init() {
this.closed = true; this.closed = true;
this.emit('close'); this.emit('close');
}); });
}; }
ProxySocket.prototype.connect = function connect(port, host) { connect(port, host) {
this.remoteAddress = host; this.remoteAddress = host;
this.remotePort = port; this.remotePort = port;
@ -144,23 +140,23 @@ ProxySocket.prototype.connect = function connect(port, host) {
this.write(chunk); this.write(chunk);
this.sendBuffer.length = 0; this.sendBuffer.length = 0;
}; }
ProxySocket.prototype.setKeepAlive = function setKeepAlive(enable, delay) { setKeepAlive(enable, delay) {
this.socket.fire('tcp keep alive', enable, delay); this.socket.fire('tcp keep alive', enable, delay);
}; }
ProxySocket.prototype.setNoDelay = function setNoDelay(enable) { setNoDelay(enable) {
this.socket.fire('tcp no delay', enable); this.socket.fire('tcp no delay', enable);
}; }
ProxySocket.prototype.setTimeout = function setTimeout(timeout, callback) { setTimeout(timeout, callback) {
this.socket.fire('tcp set timeout', timeout); this.socket.fire('tcp set timeout', timeout);
if (callback) if (callback)
this.on('timeout', callback); this.on('timeout', callback);
}; }
ProxySocket.prototype.write = function write(data, callback) { write(data, callback) {
if (!this.info) { if (!this.info) {
this.sendBuffer.push(data); this.sendBuffer.push(data);
@ -178,13 +174,13 @@ ProxySocket.prototype.write = function write(data, callback) {
callback(); callback();
return true; return true;
}; }
ProxySocket.prototype.pause = function pause() { pause() {
this.paused = true; this.paused = true;
}; }
ProxySocket.prototype.resume = function resume() { resume() {
const recv = this.recvBuffer; const recv = this.recvBuffer;
this.paused = false; this.paused = false;
@ -194,19 +190,20 @@ ProxySocket.prototype.resume = function resume() {
this.bytesRead += data.length; this.bytesRead += data.length;
this.emit('data', data); this.emit('data', data);
} }
}; }
ProxySocket.prototype.destroy = function destroy() { destroy() {
if (this.closed) if (this.closed)
return; return;
this.closed = true; this.closed = true;
this.socket.destroy(); this.socket.destroy();
}; }
ProxySocket.connect = function connect(uri, port, host) { static connect(uri, port, host) {
const socket = new ProxySocket(uri); const socket = new this(uri);
socket.connect(port, host); socket.connect(port, host);
return socket; return socket;
}; }
}
module.exports = ProxySocket; module.exports = ProxySocket;

View File

@ -12,11 +12,9 @@ const TARGET = Buffer.from(
'0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', '0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'hex'); 'hex');
function WSProxy(options) { class WSProxy extends EventEmitter {
if (!(this instanceof WSProxy)) constructor(options) {
return new WSProxy(options); super();
EventEmitter.call(this);
if (!options) if (!options)
options = {}; options = {};
@ -34,11 +32,9 @@ function WSProxy(options) {
} }
this.init(); this.init();
} }
Object.setPrototypeOf(WSProxy.prototype, EventEmitter.prototype); init() {
WSProxy.prototype.init = function init() {
this.io.on('error', (err) => { this.io.on('error', (err) => {
this.emit('error', err); this.emit('error', err);
}); });
@ -46,9 +42,9 @@ WSProxy.prototype.init = function init() {
this.io.on('socket', (ws) => { this.io.on('socket', (ws) => {
this.handleSocket(ws); this.handleSocket(ws);
}); });
}; }
WSProxy.prototype.handleSocket = function handleSocket(ws) { handleSocket(ws) {
const state = new SocketState(this, ws); const state = new SocketState(this, ws);
// Use a weak map to avoid // Use a weak map to avoid
@ -64,9 +60,9 @@ WSProxy.prototype.handleSocket = function handleSocket(ws) {
ws.bind('tcp connect', (port, host, nonce) => { ws.bind('tcp connect', (port, host, nonce) => {
this.handleConnect(ws, port, host, nonce); this.handleConnect(ws, port, host, nonce);
}); });
}; }
WSProxy.prototype.handleConnect = function handleConnect(ws, port, host, nonce) { handleConnect(ws, port, host, nonce) {
const state = this.sockets.get(ws); const state = this.sockets.get(ws);
assert(state); assert(state);
@ -213,39 +209,42 @@ WSProxy.prototype.handleConnect = function handleConnect(ws, port, host, nonce)
ws.bind('disconnect', () => { ws.bind('disconnect', () => {
socket.destroy(); socket.destroy();
}); });
}; }
WSProxy.prototype.log = function log(...args) { log(...args) {
process.stdout.write('wsproxy: '); process.stdout.write('wsproxy: ');
console.log(...args); console.log(...args);
}; }
WSProxy.prototype.attach = function attach(server) { attach(server) {
this.io.attach(server); this.io.attach(server);
}; }
}
function SocketState(server, socket) { class SocketState {
constructor(server, socket) {
this.pow = server.pow; this.pow = server.pow;
this.target = server.target; this.target = server.target;
this.snonce = nonce(); this.snonce = nonce();
this.socket = null; this.socket = null;
this.host = socket.host; this.host = socket.host;
this.remoteHost = null; this.remoteHost = null;
} }
SocketState.prototype.toInfo = function toInfo() { toInfo() {
return { return {
pow: this.pow, pow: this.pow,
target: this.target.toString('hex'), target: this.target.toString('hex'),
snonce: this.snonce.toString('hex') snonce: this.snonce.toString('hex')
}; };
}; }
SocketState.prototype.connect = function connect(port, host) { connect(port, host) {
this.socket = net.connect(port, host); this.socket = net.connect(port, host);
this.remoteHost = IP.toHostname(host, port); this.remoteHost = IP.toHostname(host, port);
return this.socket; return this.socket;
}; }
}
function nonce() { function nonce() {
const buf = Buffer.allocUnsafe(8); const buf = Buffer.allocUnsafe(8);

View File

@ -15,10 +15,8 @@ const KeyRing = require('../../lib/primitives/keyring');
const Outpoint = require('../../lib/primitives/outpoint'); const Outpoint = require('../../lib/primitives/outpoint');
const Coin = require('../../lib/primitives/coin'); const Coin = require('../../lib/primitives/coin');
function MemWallet(options) { class MemWallet {
if (!(this instanceof MemWallet)) constructor(options) {
return new MemWallet(options);
this.network = Network.primary; this.network = Network.primary;
this.master = null; this.master = null;
this.key = null; this.key = null;
@ -40,9 +38,9 @@ function MemWallet(options) {
this.fromOptions(options); this.fromOptions(options);
this.init(); this.init();
} }
MemWallet.prototype.fromOptions = function fromOptions(options) { fromOptions(options) {
if (options.network != null) { if (options.network != null) {
assert(options.network); assert(options.network);
this.network = Network.get(options.network); this.network = Network.get(options.network);
@ -79,9 +77,9 @@ MemWallet.prototype.fromOptions = function fromOptions(options) {
} }
return this; return this;
}; }
MemWallet.prototype.init = function init() { init() {
let i; let i;
if (!this.master) if (!this.master)
@ -99,9 +97,9 @@ MemWallet.prototype.init = function init() {
i = this.changeDepth; i = this.changeDepth;
while (i--) while (i--)
this.createChange(); this.createChange();
}; }
MemWallet.prototype.createReceive = function createReceive() { createReceive() {
const index = this.receiveDepth++; const index = this.receiveDepth++;
const key = this.deriveReceive(index); const key = this.deriveReceive(index);
const hash = key.getHash('hex'); const hash = key.getHash('hex');
@ -109,9 +107,9 @@ MemWallet.prototype.createReceive = function createReceive() {
this.paths.set(hash, new Path(hash, 0, index)); this.paths.set(hash, new Path(hash, 0, index));
this.receive = key; this.receive = key;
return key; return key;
}; }
MemWallet.prototype.createChange = function createChange() { createChange() {
const index = this.changeDepth++; const index = this.changeDepth++;
const key = this.deriveChange(index); const key = this.deriveChange(index);
const hash = key.getHash('hex'); const hash = key.getHash('hex');
@ -119,55 +117,60 @@ MemWallet.prototype.createChange = function createChange() {
this.paths.set(hash, new Path(hash, 1, index)); this.paths.set(hash, new Path(hash, 1, index));
this.change = key; this.change = key;
return key; return key;
}; }
MemWallet.prototype.deriveReceive = function deriveReceive(index) { deriveReceive(index) {
return this.deriveKey(0, index); return this.deriveKey(0, index);
}; }
MemWallet.prototype.deriveChange = function deriveChange(index) { deriveChange(index) {
return this.deriveKey(1, index); return this.deriveKey(1, index);
}; }
MemWallet.prototype.derivePath = function derivePath(path) { derivePath(path) {
return this.deriveKey(path.branch, path.index); return this.deriveKey(path.branch, path.index);
}; }
MemWallet.prototype.deriveKey = function deriveKey(branch, index) { deriveKey(branch, index) {
const type = this.network.keyPrefix.coinType; const type = this.network.keyPrefix.coinType;
let key = this.master.deriveAccount(44, type, this.account); let key = this.master.deriveAccount(44, type, this.account);
key = key.derive(branch).derive(index); key = key.derive(branch).derive(index);
const ring = new KeyRing({ const ring = new KeyRing({
network: this.network, network: this.network,
privateKey: key.privateKey, privateKey: key.privateKey,
witness: this.witness witness: this.witness
}); });
ring.witness = this.witness;
return ring;
};
MemWallet.prototype.getKey = function getKey(hash) { ring.witness = this.witness;
return ring;
}
getKey(hash) {
const path = this.paths.get(hash); const path = this.paths.get(hash);
if (!path) if (!path)
return null; return null;
return this.derivePath(path); return this.derivePath(path);
}; }
MemWallet.prototype.getPath = function getPath(hash) { getPath(hash) {
return this.paths.get(hash); return this.paths.get(hash);
}; }
MemWallet.prototype.getCoin = function getCoin(key) { getCoin(key) {
return this.coins.get(key); return this.coins.get(key);
}; }
MemWallet.prototype.getUndo = function getUndo(key) { getUndo(key) {
return this.spent.get(key); return this.spent.get(key);
}; }
MemWallet.prototype.addCoin = function addCoin(coin) { addCoin(coin) {
const op = new Outpoint(coin.hash, coin.index); const op = new Outpoint(coin.hash, coin.index);
const key = op.toKey(); const key = op.toKey();
@ -177,9 +180,9 @@ MemWallet.prototype.addCoin = function addCoin(coin) {
this.coins.set(key, coin); this.coins.set(key, coin);
this.balance += coin.value; this.balance += coin.value;
}; }
MemWallet.prototype.removeCoin = function removeCoin(key) { removeCoin(key) {
const coin = this.coins.get(key); const coin = this.coins.get(key);
if (!coin) if (!coin)
@ -189,30 +192,30 @@ MemWallet.prototype.removeCoin = function removeCoin(key) {
this.balance -= coin.value; this.balance -= coin.value;
this.coins.delete(key); this.coins.delete(key);
}; }
MemWallet.prototype.getAddress = function getAddress() { getAddress() {
return this.receive.getAddress(); return this.receive.getAddress();
}; }
MemWallet.prototype.getReceive = function getReceive() { getReceive() {
return this.receive.getAddress(); return this.receive.getAddress();
}; }
MemWallet.prototype.getChange = function getChange() { getChange() {
return this.change.getAddress(); return this.change.getAddress();
}; }
MemWallet.prototype.getCoins = function getCoins() { getCoins() {
const coins = []; const coins = [];
for (const coin of this.coins.values()) for (const coin of this.coins.values())
coins.push(coin); coins.push(coin);
return coins; return coins;
}; }
MemWallet.prototype.syncKey = function syncKey(path) { syncKey(path) {
switch (path.branch) { switch (path.branch) {
case 0: case 0:
if (path.index === this.receiveDepth - 1) if (path.index === this.receiveDepth - 1)
@ -226,23 +229,23 @@ MemWallet.prototype.syncKey = function syncKey(path) {
assert(false); assert(false);
break; break;
} }
}; }
MemWallet.prototype.addBlock = function addBlock(entry, txs) { addBlock(entry, txs) {
for (let i = 0; i < txs.length; i++) { for (let i = 0; i < txs.length; i++) {
const tx = txs[i]; const tx = txs[i];
this.addTX(tx, entry.height); this.addTX(tx, entry.height);
} }
}; }
MemWallet.prototype.removeBlock = function removeBlock(entry, txs) { removeBlock(entry, txs) {
for (let i = txs.length - 1; i >= 0; i--) { for (let i = txs.length - 1; i >= 0; i--) {
const tx = txs[i]; const tx = txs[i];
this.removeTX(tx, entry.height); this.removeTX(tx, entry.height);
} }
}; }
MemWallet.prototype.addTX = function addTX(tx, height) { addTX(tx, height) {
const hash = tx.hash('hex'); const hash = tx.hash('hex');
let result = false; let result = false;
@ -286,14 +289,14 @@ MemWallet.prototype.addTX = function addTX(tx, height) {
} }
if (result) { if (result) {
this.txs++; this.txs += 1;
this.map.add(hash); this.map.add(hash);
} }
return result; return result;
}; }
MemWallet.prototype.removeTX = function removeTX(tx, height) { removeTX(tx, height) {
const hash = tx.hash('hex'); const hash = tx.hash('hex');
let result = false; let result = false;
@ -326,14 +329,14 @@ MemWallet.prototype.removeTX = function removeTX(tx, height) {
} }
if (result) if (result)
this.txs--; this.txs -= 1;
this.map.delete(hash); this.map.delete(hash);
return result; return result;
}; }
MemWallet.prototype.deriveInputs = function deriveInputs(mtx) { deriveInputs(mtx) {
const keys = []; const keys = [];
for (let i = 0; i < mtx.inputs.length; i++) { for (let i = 0; i < mtx.inputs.length; i++) {
@ -359,9 +362,9 @@ MemWallet.prototype.deriveInputs = function deriveInputs(mtx) {
} }
return keys; return keys;
}; }
MemWallet.prototype.fund = function fund(mtx, options) { fund(mtx, options) {
const coins = this.getCoins(); const coins = this.getCoins();
if (!options) if (!options)
@ -378,20 +381,20 @@ MemWallet.prototype.fund = function fund(mtx, options) {
rate: options.rate, rate: options.rate,
maxFee: options.maxFee maxFee: options.maxFee
}); });
}; }
MemWallet.prototype.template = function template(mtx) { template(mtx) {
const keys = this.deriveInputs(mtx); const keys = this.deriveInputs(mtx);
mtx.template(keys); mtx.template(keys);
}; }
MemWallet.prototype.sign = function sign(mtx) { sign(mtx) {
const keys = this.deriveInputs(mtx); const keys = this.deriveInputs(mtx);
mtx.template(keys); mtx.template(keys);
mtx.sign(keys); mtx.sign(keys);
}; }
MemWallet.prototype.create = async function create(options) { async create(options) {
const mtx = new MTX(options); const mtx = new MTX(options);
await this.fund(mtx, options); await this.fund(mtx, options);
@ -409,18 +412,21 @@ MemWallet.prototype.create = async function create(options) {
throw new Error('Cannot sign tx.'); throw new Error('Cannot sign tx.');
return mtx; return mtx;
}; }
MemWallet.prototype.send = async function send(options) { async send(options) {
const mtx = await this.create(options); const mtx = await this.create(options);
this.addTX(mtx.toTX()); this.addTX(mtx.toTX());
return mtx; return mtx;
}; }
}
function Path(hash, branch, index) { class Path {
constructor(hash, branch, index) {
this.hash = hash; this.hash = hash;
this.branch = branch; this.branch = branch;
this.index = index; this.index = index;
}
} }
module.exports = MemWallet; module.exports = MemWallet;

View File

@ -5,20 +5,19 @@ const FullNode = require('../../lib/node/fullnode');
const Network = require('../../lib/protocol/network'); const Network = require('../../lib/protocol/network');
const Logger = require('blgr'); const Logger = require('blgr');
function NodeContext(network, size) { class NodeContext {
if (!(this instanceof NodeContext)) constructor(network, size) {
return new NodeContext(network, size);
this.network = Network.get(network); this.network = Network.get(network);
this.size = size || 4; this.size = size || 4;
this.nodes = []; this.nodes = [];
this.init(); this.init();
}; }
NodeContext.prototype.init = function init() { init() {
for (let i = 0; i < this.size; i++) { for (let i = 0; i < this.size; i++) {
const port = this.network.port + i; const port = this.network.port + i;
let last = port - 1; let last = port - 1;
if (last < this.network.port) if (last < this.network.port)
@ -49,55 +48,55 @@ NodeContext.prototype.init = function init() {
this.nodes.push(node); this.nodes.push(node);
} }
}; }
NodeContext.prototype.open = function open() { open() {
const jobs = []; const jobs = [];
for (const node of this.nodes) for (const node of this.nodes)
jobs.push(node.open()); jobs.push(node.open());
return Promise.all(jobs); return Promise.all(jobs);
}; }
NodeContext.prototype.close = function close() { close() {
const jobs = []; const jobs = [];
for (const node of this.nodes) for (const node of this.nodes)
jobs.push(node.close()); jobs.push(node.close());
return Promise.all(jobs); return Promise.all(jobs);
}; }
NodeContext.prototype.connect = async function connect() { async connect() {
for (const node of this.nodes) { for (const node of this.nodes) {
await node.connect(); await node.connect();
await new Promise(r => setTimeout(r, 1000)); await new Promise(r => setTimeout(r, 1000));
} }
}; }
NodeContext.prototype.disconnect = async function disconnect() { async disconnect() {
for (let i = this.nodes.length - 1; i >= 0; i--) { for (let i = this.nodes.length - 1; i >= 0; i--) {
const node = this.nodes[i]; const node = this.nodes[i];
await node.disconnect(); await node.disconnect();
await new Promise(r => setTimeout(r, 1000)); await new Promise(r => setTimeout(r, 1000));
} }
}; }
NodeContext.prototype.startSync = function startSync() { startSync() {
for (const node of this.nodes) { for (const node of this.nodes) {
node.chain.synced = true; node.chain.synced = true;
node.chain.emit('full'); node.chain.emit('full');
node.startSync(); node.startSync();
} }
}; }
NodeContext.prototype.stopSync = function stopSync() { stopSync() {
for (const node of this.nodes) for (const node of this.nodes)
node.stopSync(); node.stopSync();
}; }
NodeContext.prototype.generate = async function generate(index, blocks) { async generate(index, blocks) {
const node = this.nodes[index]; const node = this.nodes[index];
assert(node); assert(node);
@ -106,18 +105,19 @@ NodeContext.prototype.generate = async function generate(index, blocks) {
const block = await node.miner.mineBlock(); const block = await node.miner.mineBlock();
await node.chain.add(block); await node.chain.add(block);
} }
}; }
NodeContext.prototype.height = function height(index) { height(index) {
const node = this.nodes[index]; const node = this.nodes[index];
assert(node); assert(node);
return node.chain.height; return node.chain.height;
}; }
NodeContext.prototype.sync = async function sync() { async sync() {
return new Promise(r => setTimeout(r, 3000)); return new Promise(r => setTimeout(r, 3000));
}; }
}
module.exports = NodeContext; module.exports = NodeContext;