refactor: more work.
This commit is contained in:
parent
60d162eb20
commit
ae83aa6fba
748
bin/cli
748
bin/cli
@ -27,159 +27,135 @@ CLI.prototype.log = function log(json) {
|
|||||||
console.log(JSON.stringify(json, null, 2));
|
console.log(JSON.stringify(json, null, 2));
|
||||||
};
|
};
|
||||||
|
|
||||||
CLI.prototype.createWallet = function createWallet() {
|
CLI.prototype.createWallet = co(function* createWallet() {
|
||||||
return spawn(function *() {
|
var options = { id: this.argv[0] };
|
||||||
var options = { id: this.argv[0] };
|
var wallet;
|
||||||
var wallet;
|
|
||||||
|
|
||||||
if (this.config.type)
|
if (this.config.type)
|
||||||
options.type = this.config.type;
|
options.type = this.config.type;
|
||||||
|
|
||||||
if (this.config.master)
|
if (this.config.master)
|
||||||
options.master = this.config.master;
|
options.master = this.config.master;
|
||||||
|
|
||||||
if (this.config.key)
|
if (this.config.key)
|
||||||
options.key = this.config.key;
|
options.key = this.config.key;
|
||||||
|
|
||||||
if (this.config.m)
|
if (this.config.m)
|
||||||
options.m = this.config.m >>> 0;
|
options.m = this.config.m >>> 0;
|
||||||
|
|
||||||
if (this.config.n)
|
if (this.config.n)
|
||||||
options.n = this.config.n >>> 0;
|
options.n = this.config.n >>> 0;
|
||||||
|
|
||||||
if (this.config.witness != null)
|
if (this.config.witness != null)
|
||||||
options.witness = !!this.config.witness;
|
options.witness = !!this.config.witness;
|
||||||
|
|
||||||
if (this.config.passphrase)
|
if (this.config.passphrase)
|
||||||
options.passphrase = this.config.passphrase;
|
options.passphrase = this.config.passphrase;
|
||||||
|
|
||||||
wallet = yield this.client.createWallet(options);
|
wallet = yield this.client.createWallet(options);
|
||||||
this.log(wallet);
|
this.log(wallet);
|
||||||
}, this);
|
});
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.addKey = function addKey() {
|
CLI.prototype.addKey = co(function* addKey() {
|
||||||
return spawn(function *() {
|
var key = this.argv[0];
|
||||||
var key = this.argv[0];
|
yield this.wallet.addKey(this.config.account, key);
|
||||||
yield this.wallet.addKey(this.config.account, key);
|
this.log('added');
|
||||||
this.log('added');
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.removeKey = function removeKey() {
|
CLI.prototype.removeKey = co(function* removeKey() {
|
||||||
return spawn(function *() {
|
var key = this.argv[0];
|
||||||
var key = this.argv[0];
|
yield this.wallet.removeKey(this.config.account, key);
|
||||||
yield this.wallet.removeKey(this.config.account, key);
|
this.log('removed');
|
||||||
this.log('removed');
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getAccount = function getAccount() {
|
CLI.prototype.getAccount = co(function* getAccount() {
|
||||||
return spawn(function *() {
|
var account = this.argv[0] || this.config.account;
|
||||||
var account = this.argv[0] || this.config.account;
|
yield this.wallet.getAccount(account);
|
||||||
yield this.wallet.getAccount(account);
|
this.log(account);
|
||||||
this.log(account);
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.createAccount = function createAccount() {
|
CLI.prototype.createAccount = co(function* createAccount() {
|
||||||
return spawn(function *() {
|
var name = this.argv[0];
|
||||||
var name = this.argv[0];
|
var account = yield this.wallet.createAccount(name);
|
||||||
var account = yield this.wallet.createAccount(name);
|
this.log(account);
|
||||||
this.log(account);
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.createAddress = function createAddress() {
|
CLI.prototype.createAddress = co(function* createAddress() {
|
||||||
return spawn(function *() {
|
var account = this.argv[0];
|
||||||
var account = this.argv[0];
|
var addr = yield this.wallet.createAddress(account);
|
||||||
var addr = yield this.wallet.createAddress(account);
|
this.log(addr);
|
||||||
this.log(addr);
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getAccounts = function getAccounts() {
|
CLI.prototype.getAccounts = co(function* getAccounts() {
|
||||||
return spawn(function *() {
|
var accounts = yield this.wallet.getAccounts();
|
||||||
var accounts = yield this.wallet.getAccounts();
|
this.log(accounts);
|
||||||
this.log(accounts);
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getWallet = function getWallet() {
|
CLI.prototype.getWallet = co(function* getWallet() {
|
||||||
return spawn(function *() {
|
var info = yield this.wallet.getInfo();
|
||||||
var info = yield this.wallet.getInfo();
|
this.log(wallet);
|
||||||
this.log(wallet);
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getTX = function getTX() {
|
CLI.prototype.getTX = co(function* getTX() {
|
||||||
return spawn(function *() {
|
var hash = this.argv[0];
|
||||||
var hash = this.argv[0];
|
var txs, tx;
|
||||||
var txs, tx;
|
|
||||||
|
|
||||||
if (utils.isBase58(hash)) {
|
if (utils.isBase58(hash)) {
|
||||||
txs = yield this.client.getTXByAddress(hash);
|
txs = yield this.client.getTXByAddress(hash);
|
||||||
this.log(txs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tx = yield this.client.getTX(hash);
|
|
||||||
|
|
||||||
if (!tx) {
|
|
||||||
this.log('TX not found.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(tx);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getBlock = function getBlock() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var hash = this.argv[0];
|
|
||||||
if (hash.length !== 64)
|
|
||||||
hash = +hash;
|
|
||||||
|
|
||||||
block = yield this.client.getBlock(hash);
|
|
||||||
|
|
||||||
if (!block) {
|
|
||||||
this.log('Block not found.');
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(block);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getCoin = function getCoin() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var hash = this.argv[0];
|
|
||||||
var index = this.argv[1];
|
|
||||||
var coins, coin;
|
|
||||||
|
|
||||||
if (utils.isBase58(hash)) {
|
|
||||||
coins = yield this.client.getCoinsByAddress(hash);
|
|
||||||
this.log(coins);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
coin = yield this.client.getCoin(hash, index);
|
|
||||||
|
|
||||||
if (!coin) {
|
|
||||||
this.log('Coin not found.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(coin);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getWalletHistory = function getWalletHistory() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var txs = yield this.wallet.getHistory(this.config.account);
|
|
||||||
this.log(txs);
|
this.log(txs);
|
||||||
}, this);
|
return;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
tx = yield this.client.getTX(hash);
|
||||||
|
|
||||||
|
if (!tx) {
|
||||||
|
this.log('TX not found.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log(tx);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.getBlock = co(function* getBlock() {
|
||||||
|
var hash = this.argv[0];
|
||||||
|
if (hash.length !== 64)
|
||||||
|
hash = +hash;
|
||||||
|
|
||||||
|
block = yield this.client.getBlock(hash);
|
||||||
|
|
||||||
|
if (!block) {
|
||||||
|
this.log('Block not found.');
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log(block);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.getCoin = co(function* getCoin() {
|
||||||
|
var hash = this.argv[0];
|
||||||
|
var index = this.argv[1];
|
||||||
|
var coins, coin;
|
||||||
|
|
||||||
|
if (utils.isBase58(hash)) {
|
||||||
|
coins = yield this.client.getCoinsByAddress(hash);
|
||||||
|
this.log(coins);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
coin = yield this.client.getCoin(hash, index);
|
||||||
|
|
||||||
|
if (!coin) {
|
||||||
|
this.log('Coin not found.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log(coin);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.getWalletHistory = co(function* getWalletHistory() {
|
||||||
|
var txs = yield this.wallet.getHistory(this.config.account);
|
||||||
|
this.log(txs);
|
||||||
|
});
|
||||||
|
|
||||||
CLI.prototype.listenWallet = function listenWallet() {
|
CLI.prototype.listenWallet = function listenWallet() {
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -210,283 +186,255 @@ CLI.prototype.listenWallet = function listenWallet() {
|
|||||||
return new Promise(function() {});
|
return new Promise(function() {});
|
||||||
};
|
};
|
||||||
|
|
||||||
CLI.prototype.getBalance = function getBalance() {
|
CLI.prototype.getBalance = co(function* getBalance() {
|
||||||
return spawn(function *() {
|
var balance = yield this.wallet.getBalance(this.config.account);
|
||||||
var balance = yield this.wallet.getBalance(this.config.account);
|
this.log(balance);
|
||||||
this.log(balance);
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getMempool = function getMempool() {
|
CLI.prototype.getMempool = co(function* getMempool() {
|
||||||
return spawn(function *() {
|
var txs = yield this.client.getMempool();
|
||||||
var txs = yield this.client.getMempool();
|
this.log(txs);
|
||||||
this.log(txs);
|
});
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.sendTX = function sendTX() {
|
CLI.prototype.sendTX = co(function* sendTX() {
|
||||||
return spawn(function *() {
|
var output = {};
|
||||||
var output = {};
|
var options, tx;
|
||||||
var options, tx;
|
|
||||||
|
|
||||||
if (this.config.script) {
|
if (this.config.script) {
|
||||||
output.script = this.config.script;
|
output.script = this.config.script;
|
||||||
output.value = utils.satoshi(this.config.value || this.argv[0]);
|
output.value = utils.satoshi(this.config.value || this.argv[0]);
|
||||||
} else {
|
} else {
|
||||||
output.address = this.config.address || this.argv[0];
|
output.address = this.config.address || this.argv[0];
|
||||||
output.value = utils.satoshi(this.config.value || this.argv[1]);
|
output.value = utils.satoshi(this.config.value || this.argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
options = {
|
||||||
|
account: this.config.account,
|
||||||
|
passphrase: this.config.passphrase,
|
||||||
|
outputs: [output]
|
||||||
|
};
|
||||||
|
|
||||||
|
tx = yield this.wallet.send(options);
|
||||||
|
|
||||||
|
this.log(tx);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.createTX = co(function* createTX() {
|
||||||
|
var output = {};
|
||||||
|
var options, tx;
|
||||||
|
|
||||||
|
if (this.config.script) {
|
||||||
|
output.script = this.config.script;
|
||||||
|
output.value = utils.satoshi(this.config.value || this.argv[0]);
|
||||||
|
} else {
|
||||||
|
output.address = this.config.address || this.argv[0];
|
||||||
|
output.value = utils.satoshi(this.config.value || this.argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
options = {
|
||||||
|
account: this.config.account,
|
||||||
|
passphrase: this.config.passphrase,
|
||||||
|
outputs: [output]
|
||||||
|
};
|
||||||
|
|
||||||
|
tx = yield this.wallet.createTX(options);
|
||||||
|
|
||||||
|
this.log(tx);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.signTX = co(function* signTX() {
|
||||||
|
var options = { passphrase: this.config.passphrase };
|
||||||
|
var raw = options.tx || this.argv[0];
|
||||||
|
var tx = yield this.wallet.sign(raw, options);
|
||||||
|
this.log(tx);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.zap = co(function* zap() {
|
||||||
|
var age = (this.config.age >>> 0) || 72 * 60 * 60;
|
||||||
|
yield this.wallet.zap(this.config.account, age);
|
||||||
|
this.log('Zapped!');
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.broadcast = co(function* broadcast() {
|
||||||
|
var self = this;
|
||||||
|
var raw = this.argv[0] || this.config.tx;
|
||||||
|
var tx = yield this.client.broadcast(raw);
|
||||||
|
this.log('Broadcasted:');
|
||||||
|
this.log(tx);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.viewTX = co(function* viewTX() {
|
||||||
|
var raw = this.argv[0] || this.config.tx;
|
||||||
|
var tx = yield this.wallet.fill(raw);
|
||||||
|
this.log(tx);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.getDetails = co(function* getDetails() {
|
||||||
|
var hash = this.argv[0];
|
||||||
|
var details = yield this.wallet.getTX(hash);
|
||||||
|
this.log(details);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.retoken = co(function* retoken() {
|
||||||
|
var result = yield this.wallet.retoken();
|
||||||
|
this.log(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.rpc = co(function* rpc() {
|
||||||
|
var method = this.argv.shift();
|
||||||
|
var params = [];
|
||||||
|
var i, arg, param, result;
|
||||||
|
|
||||||
|
for (i = 0; i < this.argv.length; i++) {
|
||||||
|
arg = this.argv[i];
|
||||||
|
try {
|
||||||
|
param = JSON.parse(arg);
|
||||||
|
} catch (e) {
|
||||||
|
param = arg;
|
||||||
}
|
}
|
||||||
|
params.push(param);
|
||||||
|
}
|
||||||
|
|
||||||
options = {
|
result = yield this.client.rpc.call(method, params);
|
||||||
account: this.config.account,
|
|
||||||
passphrase: this.config.passphrase,
|
|
||||||
outputs: [output]
|
|
||||||
};
|
|
||||||
|
|
||||||
tx = yield this.wallet.send(options);
|
this.log(result);
|
||||||
|
});
|
||||||
|
|
||||||
this.log(tx);
|
CLI.prototype.handleWallet = co(function* handleWallet() {
|
||||||
}, this);
|
var options = {
|
||||||
};
|
id: this.config.id || 'primary',
|
||||||
|
token: this.config.token
|
||||||
|
};
|
||||||
|
|
||||||
CLI.prototype.createTX = function createTX() {
|
this.wallet = new Wallet({
|
||||||
return spawn(function *() {
|
uri: this.config.url || this.config.uri,
|
||||||
var output = {};
|
apiKey: this.config.apikey,
|
||||||
var options, tx;
|
network: this.config.network
|
||||||
|
});
|
||||||
|
|
||||||
if (this.config.script) {
|
yield this.wallet.open(options);
|
||||||
output.script = this.config.script;
|
|
||||||
output.value = utils.satoshi(this.config.value || this.argv[0]);
|
|
||||||
} else {
|
|
||||||
output.address = this.config.address || this.argv[0];
|
|
||||||
output.value = utils.satoshi(this.config.value || this.argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
options = {
|
switch (this.argv.shift()) {
|
||||||
account: this.config.account,
|
case 'listen':
|
||||||
passphrase: this.config.passphrase,
|
return yield this.listenWallet();
|
||||||
outputs: [output]
|
case 'get':
|
||||||
};
|
return yield this.getWallet();
|
||||||
|
case 'addkey':
|
||||||
tx = yield this.wallet.createTX(options);
|
return yield this.addKey();
|
||||||
|
case 'rmkey':
|
||||||
this.log(tx);
|
return yield this.removeKey();
|
||||||
}, this);
|
case 'balance':
|
||||||
};
|
return yield this.getBalance();
|
||||||
|
case 'history':
|
||||||
CLI.prototype.signTX = function signTX() {
|
return yield this.getWalletHistory();
|
||||||
return spawn(function *() {
|
case 'account':
|
||||||
var options = { passphrase: this.config.passphrase };
|
if (this.argv[0] === 'list') {
|
||||||
var raw = options.tx || this.argv[0];
|
|
||||||
var tx = yield this.wallet.sign(raw, options);
|
|
||||||
this.log(tx);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.zap = function zap() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var age = (this.config.age >>> 0) || 72 * 60 * 60;
|
|
||||||
yield this.wallet.zap(this.config.account, age);
|
|
||||||
this.log('Zapped!');
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.broadcast = function broadcast() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var self = this;
|
|
||||||
var raw = this.argv[0] || this.config.tx;
|
|
||||||
var tx = yield this.client.broadcast(raw);
|
|
||||||
this.log('Broadcasted:');
|
|
||||||
this.log(tx);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.viewTX = function viewTX() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var raw = this.argv[0] || this.config.tx;
|
|
||||||
var tx = yield this.wallet.fill(raw);
|
|
||||||
this.log(tx);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.getDetails = function getDetails() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var hash = this.argv[0];
|
|
||||||
var details = yield this.wallet.getTX(hash);
|
|
||||||
this.log(details);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.retoken = function retoken() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var result = yield this.wallet.retoken();
|
|
||||||
this.log(result);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.rpc = function rpc() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var method = this.argv.shift();
|
|
||||||
var params = [];
|
|
||||||
var i, arg, param, result;
|
|
||||||
|
|
||||||
for (i = 0; i < this.argv.length; i++) {
|
|
||||||
arg = this.argv[i];
|
|
||||||
try {
|
|
||||||
param = JSON.parse(arg);
|
|
||||||
} catch (e) {
|
|
||||||
param = arg;
|
|
||||||
}
|
|
||||||
params.push(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = yield this.client.rpc.call(method, params);
|
|
||||||
|
|
||||||
this.log(result);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.handleWallet = function handleWallet() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var options = {
|
|
||||||
id: this.config.id || 'primary',
|
|
||||||
token: this.config.token
|
|
||||||
};
|
|
||||||
|
|
||||||
this.wallet = new Wallet({
|
|
||||||
uri: this.config.url || this.config.uri,
|
|
||||||
apiKey: this.config.apikey,
|
|
||||||
network: this.config.network
|
|
||||||
});
|
|
||||||
|
|
||||||
yield this.wallet.open(options);
|
|
||||||
|
|
||||||
switch (this.argv.shift()) {
|
|
||||||
case 'listen':
|
|
||||||
return yield this.listenWallet();
|
|
||||||
case 'get':
|
|
||||||
return yield this.getWallet();
|
|
||||||
case 'addkey':
|
|
||||||
return yield this.addKey();
|
|
||||||
case 'rmkey':
|
|
||||||
return yield this.removeKey();
|
|
||||||
case 'balance':
|
|
||||||
return yield this.getBalance();
|
|
||||||
case 'history':
|
|
||||||
return yield this.getWalletHistory();
|
|
||||||
case 'account':
|
|
||||||
if (this.argv[0] === 'list') {
|
|
||||||
this.argv.shift();
|
|
||||||
return yield this.getAccounts();
|
|
||||||
}
|
|
||||||
if (this.argv[0] === 'create') {
|
|
||||||
this.argv.shift();
|
|
||||||
return yield this.createAccount();
|
|
||||||
}
|
|
||||||
if (this.argv[0] === 'get')
|
|
||||||
this.argv.shift();
|
|
||||||
return yield this.getAccount();
|
|
||||||
case 'address':
|
|
||||||
return yield this.createAddress();
|
|
||||||
case 'retoken':
|
|
||||||
return yield this.retoken();
|
|
||||||
case 'sign':
|
|
||||||
return yield this.signTX();
|
|
||||||
case 'mktx':
|
|
||||||
return yield this.createTX();
|
|
||||||
case 'send':
|
|
||||||
return yield this.sendTX();
|
|
||||||
case 'zap':
|
|
||||||
return yield this.zap();
|
|
||||||
case 'tx':
|
|
||||||
return yield this.getDetails();
|
|
||||||
case 'view':
|
|
||||||
return yield this.viewTX();
|
|
||||||
default:
|
|
||||||
this.log('Unrecognized command.');
|
|
||||||
this.log('Commands:');
|
|
||||||
this.log(' $ listen: Listen for events.');
|
|
||||||
this.log(' $ get: View wallet.');
|
|
||||||
this.log(' $ addkey [xpubkey]: Add key to wallet.');
|
|
||||||
this.log(' $ rmkey [xpubkey]: Remove key from wallet.');
|
|
||||||
this.log(' $ balance: Get wallet balance.');
|
|
||||||
this.log(' $ history: View wallet TX history.');
|
|
||||||
this.log(' $ account list: List account names.');
|
|
||||||
this.log(' $ account create [account-name]: Create account.');
|
|
||||||
this.log(' $ account get [account-name]: Get account details.');
|
|
||||||
this.log(' $ address: Derive new address.');
|
|
||||||
this.log(' $ retoken: Create new api key.');
|
|
||||||
this.log(' $ send [address] [value]: Send transaction.');
|
|
||||||
this.log(' $ mktx [address] [value]: Create transaction.');
|
|
||||||
this.log(' $ sign [tx-hex]: Sign transaction.');
|
|
||||||
this.log(' $ zap --age [age]: Zap pending wallet TXs.');
|
|
||||||
this.log(' $ tx [hash]: View transaction details.');
|
|
||||||
this.log(' $ view [tx-hex]: Parse and view transaction.');
|
|
||||||
this.log('Other Options:');
|
|
||||||
this.log(' --passphrase [passphrase]: For signing and account creation.');
|
|
||||||
this.log(' --account [account-name]: Account name.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.handleNode = function handleNode() {
|
|
||||||
return spawn(function *() {
|
|
||||||
var info;
|
|
||||||
|
|
||||||
this.client = new Client({
|
|
||||||
uri: this.config.url || this.config.uri,
|
|
||||||
apiKey: this.config.apikey,
|
|
||||||
network: this.config.network
|
|
||||||
});
|
|
||||||
|
|
||||||
info = yield this.client.getInfo();
|
|
||||||
|
|
||||||
switch (this.argv.shift()) {
|
|
||||||
case 'mkwallet':
|
|
||||||
return yield this.createWallet();
|
|
||||||
case 'broadcast':
|
|
||||||
return yield this.broadcast();
|
|
||||||
case 'mempool':
|
|
||||||
return yield this.getMempool();
|
|
||||||
case 'tx':
|
|
||||||
return yield this.getTX();
|
|
||||||
case 'coin':
|
|
||||||
return yield this.getCoin();
|
|
||||||
case 'block':
|
|
||||||
return yield this.getBlock();
|
|
||||||
case 'rpc':
|
|
||||||
return yield this.rpc();
|
|
||||||
default:
|
|
||||||
this.log('Unrecognized command.');
|
|
||||||
this.log('Commands:');
|
|
||||||
this.log(' $ wallet create [id]: Create wallet.');
|
|
||||||
this.log(' $ broadcast [tx-hex]: Broadcast transaction.');
|
|
||||||
this.log(' $ mempool: Get mempool snapshot.');
|
|
||||||
this.log(' $ tx [hash/address]: View transactions.');
|
|
||||||
this.log(' $ coin [hash+index/address]: View coins.');
|
|
||||||
this.log(' $ block [hash/height]: View block.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
CLI.prototype.open = function open() {
|
|
||||||
return spawn(function *() {
|
|
||||||
switch (this.argv[0]) {
|
|
||||||
case 'w':
|
|
||||||
case 'wallet':
|
|
||||||
this.argv.shift();
|
this.argv.shift();
|
||||||
if (this.argv[0] === 'create') {
|
return yield this.getAccounts();
|
||||||
this.argv[0] = 'mkwallet';
|
}
|
||||||
return yield this.handleNode();
|
if (this.argv[0] === 'create') {
|
||||||
}
|
this.argv.shift();
|
||||||
return yield this.handleWallet();
|
return yield this.createAccount();
|
||||||
default:
|
}
|
||||||
|
if (this.argv[0] === 'get')
|
||||||
|
this.argv.shift();
|
||||||
|
return yield this.getAccount();
|
||||||
|
case 'address':
|
||||||
|
return yield this.createAddress();
|
||||||
|
case 'retoken':
|
||||||
|
return yield this.retoken();
|
||||||
|
case 'sign':
|
||||||
|
return yield this.signTX();
|
||||||
|
case 'mktx':
|
||||||
|
return yield this.createTX();
|
||||||
|
case 'send':
|
||||||
|
return yield this.sendTX();
|
||||||
|
case 'zap':
|
||||||
|
return yield this.zap();
|
||||||
|
case 'tx':
|
||||||
|
return yield this.getDetails();
|
||||||
|
case 'view':
|
||||||
|
return yield this.viewTX();
|
||||||
|
default:
|
||||||
|
this.log('Unrecognized command.');
|
||||||
|
this.log('Commands:');
|
||||||
|
this.log(' $ listen: Listen for events.');
|
||||||
|
this.log(' $ get: View wallet.');
|
||||||
|
this.log(' $ addkey [xpubkey]: Add key to wallet.');
|
||||||
|
this.log(' $ rmkey [xpubkey]: Remove key from wallet.');
|
||||||
|
this.log(' $ balance: Get wallet balance.');
|
||||||
|
this.log(' $ history: View wallet TX history.');
|
||||||
|
this.log(' $ account list: List account names.');
|
||||||
|
this.log(' $ account create [account-name]: Create account.');
|
||||||
|
this.log(' $ account get [account-name]: Get account details.');
|
||||||
|
this.log(' $ address: Derive new address.');
|
||||||
|
this.log(' $ retoken: Create new api key.');
|
||||||
|
this.log(' $ send [address] [value]: Send transaction.');
|
||||||
|
this.log(' $ mktx [address] [value]: Create transaction.');
|
||||||
|
this.log(' $ sign [tx-hex]: Sign transaction.');
|
||||||
|
this.log(' $ zap --age [age]: Zap pending wallet TXs.');
|
||||||
|
this.log(' $ tx [hash]: View transaction details.');
|
||||||
|
this.log(' $ view [tx-hex]: Parse and view transaction.');
|
||||||
|
this.log('Other Options:');
|
||||||
|
this.log(' --passphrase [passphrase]: For signing and account creation.');
|
||||||
|
this.log(' --account [account-name]: Account name.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.handleNode = co(function* handleNode() {
|
||||||
|
var info;
|
||||||
|
|
||||||
|
this.client = new Client({
|
||||||
|
uri: this.config.url || this.config.uri,
|
||||||
|
apiKey: this.config.apikey,
|
||||||
|
network: this.config.network
|
||||||
|
});
|
||||||
|
|
||||||
|
info = yield this.client.getInfo();
|
||||||
|
|
||||||
|
switch (this.argv.shift()) {
|
||||||
|
case 'mkwallet':
|
||||||
|
return yield this.createWallet();
|
||||||
|
case 'broadcast':
|
||||||
|
return yield this.broadcast();
|
||||||
|
case 'mempool':
|
||||||
|
return yield this.getMempool();
|
||||||
|
case 'tx':
|
||||||
|
return yield this.getTX();
|
||||||
|
case 'coin':
|
||||||
|
return yield this.getCoin();
|
||||||
|
case 'block':
|
||||||
|
return yield this.getBlock();
|
||||||
|
case 'rpc':
|
||||||
|
return yield this.rpc();
|
||||||
|
default:
|
||||||
|
this.log('Unrecognized command.');
|
||||||
|
this.log('Commands:');
|
||||||
|
this.log(' $ wallet create [id]: Create wallet.');
|
||||||
|
this.log(' $ broadcast [tx-hex]: Broadcast transaction.');
|
||||||
|
this.log(' $ mempool: Get mempool snapshot.');
|
||||||
|
this.log(' $ tx [hash/address]: View transactions.');
|
||||||
|
this.log(' $ coin [hash+index/address]: View coins.');
|
||||||
|
this.log(' $ block [hash/height]: View block.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CLI.prototype.open = co(function* open() {
|
||||||
|
switch (this.argv[0]) {
|
||||||
|
case 'w':
|
||||||
|
case 'wallet':
|
||||||
|
this.argv.shift();
|
||||||
|
if (this.argv[0] === 'create') {
|
||||||
|
this.argv[0] = 'mkwallet';
|
||||||
return yield this.handleNode();
|
return yield this.handleNode();
|
||||||
}
|
}
|
||||||
}, this);
|
return yield this.handleWallet();
|
||||||
};
|
default:
|
||||||
|
return yield this.handleNode();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
CLI.prototype.destroy = function destroy() {
|
CLI.prototype.destroy = function destroy() {
|
||||||
if (this.wallet && !this.wallet.client.loading)
|
if (this.wallet && !this.wallet.client.loading)
|
||||||
|
|||||||
@ -1223,7 +1223,7 @@ Chain.prototype.add = co(function* add(block) {
|
|||||||
if (this.orphan.size > this.orphanLimit)
|
if (this.orphan.size > this.orphanLimit)
|
||||||
this.pruneOrphans();
|
this.pruneOrphans();
|
||||||
|
|
||||||
yield utils.wait();
|
yield spawn.wait();
|
||||||
|
|
||||||
if (!this.synced && this.isFull()) {
|
if (!this.synced && this.isFull()) {
|
||||||
this.synced = true;
|
this.synced = true;
|
||||||
|
|||||||
@ -235,7 +235,7 @@ ChainEntry.prototype.getAncestorByHeight = co(function* getAncestorByHeight(heig
|
|||||||
var main, entry;
|
var main, entry;
|
||||||
|
|
||||||
if (height < 0)
|
if (height < 0)
|
||||||
return yield utils.wait();
|
return yield spawn.wait();
|
||||||
|
|
||||||
assert(height >= 0);
|
assert(height >= 0);
|
||||||
assert(height <= this.height);
|
assert(height <= this.height);
|
||||||
|
|||||||
@ -14,15 +14,16 @@ var scryptAsync = require('./scrypt-async');
|
|||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var spawn = require('../utils/spawn');
|
var spawn = require('../utils/spawn');
|
||||||
var co = spawn.co;
|
var co = spawn.co;
|
||||||
|
var wrap = spawn.wrap;
|
||||||
var native = require('../utils/native');
|
var native = require('../utils/native');
|
||||||
var nativeCrypto, hash, aes;
|
var nodeCrypto, hash, aes;
|
||||||
|
|
||||||
var isBrowser =
|
var isBrowser =
|
||||||
(typeof process !== 'undefined' && process.browser)
|
(typeof process !== 'undefined' && process.browser)
|
||||||
|| typeof window !== 'undefined';
|
|| typeof window !== 'undefined';
|
||||||
|
|
||||||
if (!isBrowser) {
|
if (!isBrowser) {
|
||||||
nativeCrypto = require('crypto');
|
nodeCrypto = require('crypto');
|
||||||
} else {
|
} else {
|
||||||
hash = require('hash.js');
|
hash = require('hash.js');
|
||||||
aes = require('./aes');
|
aes = require('./aes');
|
||||||
@ -42,10 +43,10 @@ var crypto = exports;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
crypto.hash = function _hash(alg, data) {
|
crypto.hash = function _hash(alg, data) {
|
||||||
if (!nativeCrypto)
|
if (!nodeCrypto)
|
||||||
return new Buffer(hash[alg]().update(data).digest());
|
return new Buffer(hash[alg]().update(data).digest());
|
||||||
|
|
||||||
return nativeCrypto.createHash(alg).update(data).digest();
|
return nodeCrypto.createHash(alg).update(data).digest();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (native)
|
if (native)
|
||||||
@ -131,12 +132,12 @@ crypto.checksum = function checksum(data) {
|
|||||||
crypto.hmac = function hmac(alg, data, salt) {
|
crypto.hmac = function hmac(alg, data, salt) {
|
||||||
var hmac;
|
var hmac;
|
||||||
|
|
||||||
if (!nativeCrypto) {
|
if (!nodeCrypto) {
|
||||||
hmac = hash.hmac(hash[alg], salt);
|
hmac = hash.hmac(hash[alg], salt);
|
||||||
return new Buffer(hmac.update(data).digest());
|
return new Buffer(hmac.update(data).digest());
|
||||||
}
|
}
|
||||||
|
|
||||||
hmac = nativeCrypto.createHmac(alg, salt);
|
hmac = nodeCrypto.createHmac(alg, salt);
|
||||||
return hmac.update(data).digest();
|
return hmac.update(data).digest();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -160,8 +161,8 @@ crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
|
|||||||
if (typeof salt === 'string')
|
if (typeof salt === 'string')
|
||||||
salt = new Buffer(salt, 'utf8');
|
salt = new Buffer(salt, 'utf8');
|
||||||
|
|
||||||
if (nativeCrypto && nativeCrypto.pbkdf2Sync)
|
if (nodeCrypto && nodeCrypto.pbkdf2Sync)
|
||||||
return nativeCrypto.pbkdf2Sync(key, salt, iter, len, alg);
|
return nodeCrypto.pbkdf2Sync(key, salt, iter, len, alg);
|
||||||
|
|
||||||
return crypto._pbkdf2(key, salt, iter, len, alg);
|
return crypto._pbkdf2(key, salt, iter, len, alg);
|
||||||
};
|
};
|
||||||
@ -185,13 +186,9 @@ crypto.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg) {
|
|||||||
if (typeof salt === 'string')
|
if (typeof salt === 'string')
|
||||||
salt = new Buffer(salt, 'utf8');
|
salt = new Buffer(salt, 'utf8');
|
||||||
|
|
||||||
if (nativeCrypto && nativeCrypto.pbkdf2) {
|
if (nodeCrypto && nodeCrypto.pbkdf2) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
nativeCrypto.pbkdf2(key, salt, iter, len, alg, function(err, key) {
|
nodeCrypto.pbkdf2(key, salt, iter, len, alg, wrap(resolve, reject));
|
||||||
if (err)
|
|
||||||
return reject(err);
|
|
||||||
resolve(key);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,11 +241,7 @@ crypto.scryptAsync = function _scrypt(passwd, salt, N, r, p, len) {
|
|||||||
salt = new Buffer(salt, 'utf8');
|
salt = new Buffer(salt, 'utf8');
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
scryptAsync(passwd, salt, N, r, p, len, function(err, key) {
|
scryptAsync(passwd, salt, N, r, p, len, wrap(resolve, reject));
|
||||||
if (err)
|
|
||||||
return reject(err);
|
|
||||||
resolve(key);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -270,28 +263,26 @@ crypto.derive = function derive(passphrase) {
|
|||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
crypto.encrypt = function encrypt(data, passphrase, iv) {
|
crypto.encrypt = co(function* encrypt(data, passphrase, iv) {
|
||||||
return spawn(function *() {
|
var key;
|
||||||
var key;
|
|
||||||
|
|
||||||
assert(Buffer.isBuffer(data));
|
assert(Buffer.isBuffer(data));
|
||||||
assert(passphrase, 'No passphrase.');
|
assert(passphrase, 'No passphrase.');
|
||||||
assert(Buffer.isBuffer(iv));
|
assert(Buffer.isBuffer(iv));
|
||||||
|
|
||||||
key = yield crypto.derive(passphrase);
|
key = yield crypto.derive(passphrase);
|
||||||
|
|
||||||
try {
|
|
||||||
data = crypto.encipher(data, key, iv);
|
|
||||||
} catch (e) {
|
|
||||||
key.fill(0);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
data = crypto.encipher(data, key, iv);
|
||||||
|
} catch (e) {
|
||||||
key.fill(0);
|
key.fill(0);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
key.fill(0);
|
||||||
});
|
|
||||||
};
|
return data;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt with aes-256-cbc.
|
* Encrypt with aes-256-cbc.
|
||||||
@ -304,10 +295,10 @@ crypto.encrypt = function encrypt(data, passphrase, iv) {
|
|||||||
crypto.encipher = function encipher(data, key, iv) {
|
crypto.encipher = function encipher(data, key, iv) {
|
||||||
var cipher;
|
var cipher;
|
||||||
|
|
||||||
if (!nativeCrypto)
|
if (!nodeCrypto)
|
||||||
return aes.cbc.encrypt(data, key, iv);
|
return aes.cbc.encrypt(data, key, iv);
|
||||||
|
|
||||||
cipher = nativeCrypto.createCipheriv('aes-256-cbc', key, iv);
|
cipher = nodeCrypto.createCipheriv('aes-256-cbc', key, iv);
|
||||||
|
|
||||||
return Buffer.concat([
|
return Buffer.concat([
|
||||||
cipher.update(data),
|
cipher.update(data),
|
||||||
@ -323,28 +314,26 @@ crypto.encipher = function encipher(data, key, iv) {
|
|||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
crypto.decrypt = function decrypt(data, passphrase, iv) {
|
crypto.decrypt = co(function* decrypt(data, passphrase, iv) {
|
||||||
return spawn(function *() {
|
var key;
|
||||||
var key;
|
|
||||||
|
|
||||||
assert(Buffer.isBuffer(data));
|
assert(Buffer.isBuffer(data));
|
||||||
assert(passphrase, 'No passphrase.');
|
assert(passphrase, 'No passphrase.');
|
||||||
assert(Buffer.isBuffer(iv));
|
assert(Buffer.isBuffer(iv));
|
||||||
|
|
||||||
key = yield crypto.derive(passphrase);
|
key = yield crypto.derive(passphrase);
|
||||||
|
|
||||||
try {
|
|
||||||
data = crypto.decipher(data, key, iv);
|
|
||||||
} catch (e) {
|
|
||||||
key.fill(0);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
data = crypto.decipher(data, key, iv);
|
||||||
|
} catch (e) {
|
||||||
key.fill(0);
|
key.fill(0);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
key.fill(0);
|
||||||
});
|
|
||||||
};
|
return data;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt with aes-256-cbc.
|
* Decrypt with aes-256-cbc.
|
||||||
@ -357,10 +346,10 @@ crypto.decrypt = function decrypt(data, passphrase, iv) {
|
|||||||
crypto.decipher = function decipher(data, key, iv) {
|
crypto.decipher = function decipher(data, key, iv) {
|
||||||
var decipher;
|
var decipher;
|
||||||
|
|
||||||
if (!nativeCrypto)
|
if (!nodeCrypto)
|
||||||
return aes.cbc.decrypt(data, key, iv);
|
return aes.cbc.decrypt(data, key, iv);
|
||||||
|
|
||||||
decipher = nativeCrypto.createDecipheriv('aes-256-cbc', key, iv);
|
decipher = nodeCrypto.createDecipheriv('aes-256-cbc', key, iv);
|
||||||
|
|
||||||
return Buffer.concat([
|
return Buffer.concat([
|
||||||
decipher.update(data),
|
decipher.update(data),
|
||||||
|
|||||||
@ -12,7 +12,7 @@ var assert = utils.assert;
|
|||||||
var AsyncObject = require('../utils/async');
|
var AsyncObject = require('../utils/async');
|
||||||
var spawn = require('../utils/spawn');
|
var spawn = require('../utils/spawn');
|
||||||
var co = spawn.co;
|
var co = spawn.co;
|
||||||
var P = utils.P;
|
var wrap = spawn.wrap;
|
||||||
var VERSION_ERROR;
|
var VERSION_ERROR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,7 +66,7 @@ utils.inherits(LowlevelUp, AsyncObject);
|
|||||||
LowlevelUp.prototype._open = function open() {
|
LowlevelUp.prototype._open = function open() {
|
||||||
var self = this;
|
var self = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.binding.open(self.options, P(resolve, reject));
|
self.binding.open(self.options, wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ LowlevelUp.prototype._open = function open() {
|
|||||||
LowlevelUp.prototype._close = function close() {
|
LowlevelUp.prototype._close = function close() {
|
||||||
var self = this;
|
var self = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.binding.close(P(resolve, reject));
|
self.binding.close(wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ LowlevelUp.prototype.destroy = function destroy() {
|
|||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (!self.backend.destroy)
|
if (!self.backend.destroy)
|
||||||
return utils.asyncify(reject)(new Error('Cannot destroy.'));
|
return utils.asyncify(reject)(new Error('Cannot destroy.'));
|
||||||
self.backend.destroy(self.location, P(resolve, reject));
|
self.backend.destroy(self.location, wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ LowlevelUp.prototype.repair = function repair() {
|
|||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (!self.backend.repair)
|
if (!self.backend.repair)
|
||||||
return utils.asyncify(reject)(new Error('Cannot repair.'));
|
return utils.asyncify(reject)(new Error('Cannot repair.'));
|
||||||
self.backend.repair(self.location, P(resolve, reject));
|
self.backend.repair(self.location, wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ LowlevelUp.prototype.backup = function backup(path) {
|
|||||||
return this.clone(path);
|
return this.clone(path);
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.binding.backup(path, P(resolve, reject));
|
self.binding.backup(path, wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ LowlevelUp.prototype.put = function put(key, value, options) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
assert(this.loaded, 'Cannot use database before it is loaded.');
|
assert(this.loaded, 'Cannot use database before it is loaded.');
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.binding.put(key, value, options || {}, P(resolve, reject));
|
self.binding.put(key, value, options || {}, wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ LowlevelUp.prototype.del = function del(key, options) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
assert(this.loaded, 'Cannot use database before it is loaded.');
|
assert(this.loaded, 'Cannot use database before it is loaded.');
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.binding.del(key, options || {}, P(resolve, reject));
|
self.binding.del(key, options || {}, wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ LowlevelUp.prototype.batch = function batch(ops, options) {
|
|||||||
return new Batch(this);
|
return new Batch(this);
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.binding.batch(ops, options || {}, P(resolve, reject));
|
self.binding.batch(ops, options || {}, wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ LowlevelUp.prototype.approximateSize = function approximateSize(start, end) {
|
|||||||
if (!self.binding.approximateSize)
|
if (!self.binding.approximateSize)
|
||||||
return utils.asyncify(reject)(new Error('Cannot get size.'));
|
return utils.asyncify(reject)(new Error('Cannot get size.'));
|
||||||
|
|
||||||
self.binding.approximateSize(start, end, P(resolve, reject));
|
self.binding.approximateSize(start, end, wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ Batch.prototype.del = function del(key) {
|
|||||||
Batch.prototype.write = function write() {
|
Batch.prototype.write = function write() {
|
||||||
var self = this;
|
var self = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.batch.write(P(resolve, reject));
|
self.batch.write(wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -465,7 +465,7 @@ Iterator.prototype.next = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key === undefined && value === undefined) {
|
if (key === undefined && value === undefined) {
|
||||||
self.iter.end(P(resolve, reject));
|
self.iter.end(wrap(resolve, reject));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,7 +481,7 @@ Iterator.prototype.seek = function seek(key) {
|
|||||||
Iterator.prototype.end = function end() {
|
Iterator.prototype.end = function end() {
|
||||||
var self = this;
|
var self = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.iter.end(P(resolve, reject));
|
self.iter.end(wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4145,13 +4145,13 @@ function reverseEndian(data) {
|
|||||||
|
|
||||||
function writeFile(file, data) {
|
function writeFile(file, data) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
fs.writeFile(file, data, utils.P(resolve, reject));
|
fs.writeFile(file, data, spawn.wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function readFile(file, enc) {
|
function readFile(file, enc) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
fs.readFile(file, enc, utils.P(resolve, reject));
|
fs.readFile(file, enc, spawn.wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -189,7 +189,7 @@ Mempool.prototype.addBlock = co(function* addBlock(block) {
|
|||||||
// There may be a locktime in a TX that is now valid.
|
// There may be a locktime in a TX that is now valid.
|
||||||
this.rejects.reset();
|
this.rejects.reset();
|
||||||
|
|
||||||
yield utils.wait();
|
yield spawn.wait();
|
||||||
unlock();
|
unlock();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -160,61 +160,57 @@ Miner.prototype._close = function close() {
|
|||||||
* @param {Number?} version - Custom block version.
|
* @param {Number?} version - Custom block version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Miner.prototype.start = function start() {
|
Miner.prototype.start = co(function* start() {
|
||||||
var self = this;
|
var self = this;
|
||||||
spawn(function *() {
|
var attempt, block;
|
||||||
var attempt, block;
|
|
||||||
|
|
||||||
this.stop();
|
this.stop();
|
||||||
|
|
||||||
this.running = true;
|
this.running = true;
|
||||||
|
|
||||||
// Create a new block and start hashing
|
// Create a new block and start hashing
|
||||||
try {
|
try {
|
||||||
attempt = yield this.createBlock();
|
attempt = yield this.createBlock();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.emit('error', e);
|
this.emit('error', e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.attempt = attempt;
|
||||||
|
|
||||||
|
attempt.on('status', function(status) {
|
||||||
|
self.emit('status', status);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
block = yield attempt.mineAsync();
|
||||||
|
} catch (e) {
|
||||||
if (!this.running)
|
if (!this.running)
|
||||||
return;
|
return;
|
||||||
|
this.emit('error', e);
|
||||||
|
return this.start();
|
||||||
|
}
|
||||||
|
|
||||||
this.attempt = attempt;
|
// Add our block to the chain
|
||||||
|
try {
|
||||||
|
yield this.chain.add(block);
|
||||||
|
} catch (err) {
|
||||||
|
if (err.type === 'VerifyError')
|
||||||
|
this.logger.warning('%s could not be added to chain.', block.rhash);
|
||||||
|
this.emit('error', err);
|
||||||
|
this.start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
attempt.on('status', function(status) {
|
// Emit our newly found block
|
||||||
self.emit('status', status);
|
this.emit('block', block);
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
// `tip` will now be emitted by chain
|
||||||
block = yield attempt.mineAsync();
|
// and the whole process starts over.
|
||||||
} catch (e) {
|
});
|
||||||
if (!this.running)
|
|
||||||
return;
|
|
||||||
this.emit('error', e);
|
|
||||||
return this.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add our block to the chain
|
|
||||||
try {
|
|
||||||
yield this.chain.add(block);
|
|
||||||
} catch (err) {
|
|
||||||
if (err.type === 'VerifyError')
|
|
||||||
this.logger.warning('%s could not be added to chain.', block.rhash);
|
|
||||||
this.emit('error', err);
|
|
||||||
this.start();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit our newly found block
|
|
||||||
this.emit('block', block);
|
|
||||||
|
|
||||||
// `tip` will now be emitted by chain
|
|
||||||
// and the whole process starts over.
|
|
||||||
}, this).catch(function(err) {
|
|
||||||
self.emit('error', err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop mining.
|
* Stop mining.
|
||||||
|
|||||||
394
lib/net/peer.js
394
lib/net/peer.js
@ -1119,66 +1119,71 @@ Peer.prototype._handleUTXOs = function _handleUTXOs(utxos) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(packet) {
|
Peer.prototype._handleGetUTXOs = co(function* _handleGetUTXOs(packet) {
|
||||||
var self = this;
|
var unlock = yield this._lock();
|
||||||
spawn(function *() {
|
var i, utxos, prevout, hash, index, coin;
|
||||||
var unlock = yield this._lock();
|
|
||||||
var i, utxos, prevout, hash, index, coin;
|
|
||||||
|
|
||||||
if (!this.chain.synced)
|
if (!this.chain.synced)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (this.options.selfish)
|
if (this.options.selfish)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (this.chain.db.options.spv)
|
if (this.chain.db.options.spv)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (packet.prevout.length > 15)
|
if (packet.prevout.length > 15)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
utxos = new packets.GetUTXOsPacket();
|
utxos = new packets.GetUTXOsPacket();
|
||||||
|
|
||||||
for (i = 0; i < packet.prevout.length; i++) {
|
for (i = 0; i < packet.prevout.length; i++) {
|
||||||
prevout = packet.prevout[i];
|
prevout = packet.prevout[i];
|
||||||
hash = prevout.hash;
|
hash = prevout.hash;
|
||||||
index = prevout.index;
|
index = prevout.index;
|
||||||
|
|
||||||
if (this.mempool && packet.mempool) {
|
if (this.mempool && packet.mempool) {
|
||||||
|
try {
|
||||||
coin = this.mempool.getCoin(hash, index);
|
coin = this.mempool.getCoin(hash, index);
|
||||||
|
} catch (e) {
|
||||||
if (coin) {
|
this.emit('error', e);
|
||||||
utxos.hits.push(1);
|
return;
|
||||||
utxos.coins.push(coin);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.mempool.isSpent(hash, index)) {
|
|
||||||
utxos.hits.push(0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coin = yield this.chain.db.getCoin(hash, index);
|
if (coin) {
|
||||||
|
utxos.hits.push(1);
|
||||||
if (!coin) {
|
utxos.coins.push(coin);
|
||||||
utxos.hits.push(0);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
utxos.hits.push(1);
|
if (this.mempool.isSpent(hash, index)) {
|
||||||
utxos.coins.push(coin);
|
utxos.hits.push(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
utxos.height = this.chain.height;
|
try {
|
||||||
utxos.tip = this.chain.tip.hash;
|
coin = yield this.chain.db.getCoin(hash, index);
|
||||||
|
} catch (e) {
|
||||||
|
this.emit('error', e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.send(utxos);
|
if (!coin) {
|
||||||
unlock();
|
utxos.hits.push(0);
|
||||||
}, this).catch(function(err) {
|
continue;
|
||||||
self.emit('error', err);
|
}
|
||||||
});
|
|
||||||
};
|
utxos.hits.push(1);
|
||||||
|
utxos.coins.push(coin);
|
||||||
|
}
|
||||||
|
|
||||||
|
utxos.height = this.chain.height;
|
||||||
|
utxos.tip = this.chain.tip.hash;
|
||||||
|
|
||||||
|
this.send(utxos);
|
||||||
|
unlock();
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle `havewitness` packet.
|
* Handle `havewitness` packet.
|
||||||
@ -1197,55 +1202,50 @@ Peer.prototype._handleHaveWitness = function _handleHaveWitness(packet) {
|
|||||||
* @param {GetHeadersPacket}
|
* @param {GetHeadersPacket}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleGetHeaders = function _handleGetHeaders(packet) {
|
Peer.prototype._handleGetHeaders = co(function* _handleGetHeaders(packet) {
|
||||||
var self = this;
|
var unlock = yield this._lock();
|
||||||
spawn(function *() {
|
var headers = [];
|
||||||
var unlock = yield this._lock();
|
var hash, entry;
|
||||||
var headers = [];
|
|
||||||
var hash, entry;
|
|
||||||
|
|
||||||
if (!this.chain.synced)
|
if (!this.chain.synced)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (this.options.selfish)
|
if (this.options.selfish)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (this.chain.db.options.spv)
|
if (this.chain.db.options.spv)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (this.chain.db.options.prune)
|
if (this.chain.db.options.prune)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (packet.locator.length > 0) {
|
|
||||||
hash = yield this.chain.findLocator(packet.locator);
|
|
||||||
if (hash)
|
|
||||||
hash = yield this.chain.db.getNextHash(hash);
|
|
||||||
} else {
|
|
||||||
hash = packet.stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (packet.locator.length > 0) {
|
||||||
|
hash = yield this.chain.findLocator(packet.locator);
|
||||||
if (hash)
|
if (hash)
|
||||||
entry = yield this.chain.db.get(hash);
|
hash = yield this.chain.db.getNextHash(hash);
|
||||||
|
} else {
|
||||||
|
hash = packet.stop;
|
||||||
|
}
|
||||||
|
|
||||||
while (entry) {
|
if (hash)
|
||||||
headers.push(entry.toHeaders());
|
entry = yield this.chain.db.get(hash);
|
||||||
|
|
||||||
if (headers.length === 2000)
|
while (entry) {
|
||||||
break;
|
headers.push(entry.toHeaders());
|
||||||
|
|
||||||
if (entry.hash === packet.stop)
|
if (headers.length === 2000)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
entry = yield entry.getNext();
|
if (entry.hash === packet.stop)
|
||||||
}
|
break;
|
||||||
|
|
||||||
this.sendHeaders(headers);
|
entry = yield entry.getNext();
|
||||||
|
}
|
||||||
|
|
||||||
unlock();
|
this.sendHeaders(headers);
|
||||||
}, this).catch(function(err) {
|
|
||||||
self.emit('error', err);
|
unlock();
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle `getblocks` packet.
|
* Handle `getblocks` packet.
|
||||||
@ -1253,50 +1253,45 @@ Peer.prototype._handleGetHeaders = function _handleGetHeaders(packet) {
|
|||||||
* @param {GetBlocksPacket}
|
* @param {GetBlocksPacket}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleGetBlocks = function _handleGetBlocks(packet) {
|
Peer.prototype._handleGetBlocks = co(function* _handleGetBlocks(packet) {
|
||||||
var self = this;
|
var unlock = yield this._lock();
|
||||||
spawn(function *() {
|
var blocks = [];
|
||||||
var unlock = yield this._lock();
|
var hash;
|
||||||
var blocks = [];
|
|
||||||
var hash;
|
|
||||||
|
|
||||||
if (!this.chain.synced)
|
if (!this.chain.synced)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (this.options.selfish)
|
if (this.options.selfish)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (this.chain.db.options.spv)
|
if (this.chain.db.options.spv)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
if (this.chain.db.options.prune)
|
if (this.chain.db.options.prune)
|
||||||
return unlock();
|
return unlock();
|
||||||
|
|
||||||
hash = yield this.chain.findLocator(packet.locator);
|
hash = yield this.chain.findLocator(packet.locator);
|
||||||
|
|
||||||
if (hash)
|
if (hash)
|
||||||
hash = yield this.chain.db.getNextHash(hash);
|
hash = yield this.chain.db.getNextHash(hash);
|
||||||
|
|
||||||
while (hash) {
|
while (hash) {
|
||||||
blocks.push(new InvItem(constants.inv.BLOCK, hash));
|
blocks.push(new InvItem(constants.inv.BLOCK, hash));
|
||||||
|
|
||||||
if (hash === packet.stop)
|
if (hash === packet.stop)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (blocks.length === 500) {
|
if (blocks.length === 500) {
|
||||||
this.hashContinue = hash;
|
this.hashContinue = hash;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
hash = yield this.chain.db.getNextHash(hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendInv(blocks);
|
hash = yield this.chain.db.getNextHash(hash);
|
||||||
unlock();
|
}
|
||||||
}, this).catch(function(err) {
|
|
||||||
self.emit('error', err);
|
this.sendInv(blocks);
|
||||||
});
|
unlock();
|
||||||
};
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle `version` packet.
|
* Handle `version` packet.
|
||||||
@ -1480,119 +1475,114 @@ Peer.prototype._getItem = co(function* _getItem(item) {
|
|||||||
* @param {GetDataPacket}
|
* @param {GetDataPacket}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleGetData = function _handleGetData(packet) {
|
Peer.prototype._handleGetData = co(function* _handleGetData(packet) {
|
||||||
var self = this;
|
var unlock = yield this._lock();
|
||||||
spawn(function *() {
|
var notFound = [];
|
||||||
var unlock = yield this._lock();
|
var items = packet.items;
|
||||||
var notFound = [];
|
var i, j, item, entry, tx, block;
|
||||||
var items = packet.items;
|
|
||||||
var i, j, item, entry, tx, block;
|
|
||||||
|
|
||||||
if (items.length > 50000) {
|
if (items.length > 50000) {
|
||||||
this.error('getdata size too large (%s).', items.length);
|
this.error('getdata size too large (%s).', items.length);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < items.length; i++) {
|
||||||
|
item = items[i];
|
||||||
|
entry = yield this._getItem(item);
|
||||||
|
|
||||||
|
if (!entry) {
|
||||||
|
notFound.push(item);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < items.length; i++) {
|
if (item.isTX()) {
|
||||||
item = items[i];
|
tx = entry;
|
||||||
entry = yield this._getItem(item);
|
|
||||||
|
|
||||||
if (!entry) {
|
// Coinbases are an insta-ban from any node.
|
||||||
|
// This should technically never happen, but
|
||||||
|
// it's worth keeping here just in case. A
|
||||||
|
// 24-hour ban from any node is rough.
|
||||||
|
if (tx.isCoinbase()) {
|
||||||
notFound.push(item);
|
notFound.push(item);
|
||||||
|
this.logger.warning('Failsafe: tried to relay a coinbase.');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.isTX()) {
|
this.send(new packets.TXPacket(tx, item.hasWitness()));
|
||||||
tx = entry;
|
|
||||||
|
|
||||||
// Coinbases are an insta-ban from any node.
|
continue;
|
||||||
// This should technically never happen, but
|
}
|
||||||
// it's worth keeping here just in case. A
|
|
||||||
// 24-hour ban from any node is rough.
|
block = entry;
|
||||||
if (tx.isCoinbase()) {
|
|
||||||
|
switch (item.type) {
|
||||||
|
case constants.inv.BLOCK:
|
||||||
|
case constants.inv.WITNESS_BLOCK:
|
||||||
|
this.send(new packets.BlockPacket(block, item.hasWitness()));
|
||||||
|
break;
|
||||||
|
case constants.inv.FILTERED_BLOCK:
|
||||||
|
case constants.inv.WITNESS_FILTERED_BLOCK:
|
||||||
|
if (!this.spvFilter) {
|
||||||
notFound.push(item);
|
notFound.push(item);
|
||||||
this.logger.warning('Failsafe: tried to relay a coinbase.');
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.send(new packets.TXPacket(tx, item.hasWitness()));
|
block = block.toMerkle(this.spvFilter);
|
||||||
|
|
||||||
continue;
|
this.send(new packets.MerkleBlockPacket(block));
|
||||||
}
|
|
||||||
|
|
||||||
block = entry;
|
for (j = 0; j < block.txs.length; j++) {
|
||||||
|
tx = block.txs[j];
|
||||||
|
this.send(new packets.TXPacket(tx, item.hasWitness()));
|
||||||
|
}
|
||||||
|
|
||||||
switch (item.type) {
|
break;
|
||||||
case constants.inv.BLOCK:
|
case constants.inv.CMPCT_BLOCK:
|
||||||
case constants.inv.WITNESS_BLOCK:
|
// Fallback to full block.
|
||||||
this.send(new packets.BlockPacket(block, item.hasWitness()));
|
if (block.height < this.chain.tip.height - 10) {
|
||||||
|
this.send(new packets.BlockPacket(block, false));
|
||||||
break;
|
break;
|
||||||
case constants.inv.FILTERED_BLOCK:
|
}
|
||||||
case constants.inv.WITNESS_FILTERED_BLOCK:
|
|
||||||
if (!this.spvFilter) {
|
// Try again with a new nonce
|
||||||
notFound.push(item);
|
// if we get a siphash collision.
|
||||||
|
for (;;) {
|
||||||
|
try {
|
||||||
|
block = bcoin.bip152.CompactBlock.fromBlock(block);
|
||||||
|
} catch (e) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
block = block.toMerkle(this.spvFilter);
|
|
||||||
|
|
||||||
this.send(new packets.MerkleBlockPacket(block));
|
|
||||||
|
|
||||||
for (j = 0; j < block.txs.length; j++) {
|
|
||||||
tx = block.txs[j];
|
|
||||||
this.send(new packets.TXPacket(tx, item.hasWitness()));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case constants.inv.CMPCT_BLOCK:
|
}
|
||||||
// Fallback to full block.
|
|
||||||
if (block.height < this.chain.tip.height - 10) {
|
|
||||||
this.send(new packets.BlockPacket(block, false));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try again with a new nonce
|
this.send(new packets.CmpctBlockPacket(block, false));
|
||||||
// if we get a siphash collision.
|
break;
|
||||||
for (;;) {
|
default:
|
||||||
try {
|
this.logger.warning(
|
||||||
block = bcoin.bip152.CompactBlock.fromBlock(block);
|
'Peer sent an unknown getdata type: %s (%s).',
|
||||||
} catch (e) {
|
item.type,
|
||||||
continue;
|
this.hostname);
|
||||||
}
|
notFound.push(item);
|
||||||
break;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
this.send(new packets.CmpctBlockPacket(block, false));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.logger.warning(
|
|
||||||
'Peer sent an unknown getdata type: %s (%s).',
|
|
||||||
item.type,
|
|
||||||
this.hostname);
|
|
||||||
notFound.push(item);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.hash === this.hashContinue) {
|
|
||||||
this.sendInv(new InvItem(constants.inv.BLOCK, this.chain.tip.hash));
|
|
||||||
this.hashContinue = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.debug(
|
if (item.hash === this.hashContinue) {
|
||||||
'Served %d items with getdata (notfound=%d) (%s).',
|
this.sendInv(new InvItem(constants.inv.BLOCK, this.chain.tip.hash));
|
||||||
items.length - notFound.length,
|
this.hashContinue = null;
|
||||||
notFound.length,
|
}
|
||||||
this.hostname);
|
}
|
||||||
|
|
||||||
if (notFound.length > 0)
|
this.logger.debug(
|
||||||
this.send(new packets.NotFoundPacket(notFound));
|
'Served %d items with getdata (notfound=%d) (%s).',
|
||||||
|
items.length - notFound.length,
|
||||||
|
notFound.length,
|
||||||
|
this.hostname);
|
||||||
|
|
||||||
unlock();
|
if (notFound.length > 0)
|
||||||
}, this).catch(function(err) {
|
this.send(new packets.NotFoundPacket(notFound));
|
||||||
self.emit('error', err);
|
|
||||||
});
|
unlock();
|
||||||
};
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle `notfound` packet.
|
* Handle `notfound` packet.
|
||||||
|
|||||||
@ -431,7 +431,7 @@ Pool.prototype.listen = function listen() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.server.listen(self.port, '0.0.0.0', utils.P(resolve, reject));
|
self.server.listen(self.port, '0.0.0.0', spawn.wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -450,7 +450,7 @@ Pool.prototype.unlisten = function unlisten() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.server.close(utils.P(resolve, reject));
|
self.server.close(spawn.wrap(resolve, reject));
|
||||||
self.server = null;
|
self.server = null;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -902,7 +902,7 @@ Pool.prototype._handleBlock = co(function* _handleBlock(block, peer) {
|
|||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
'Received unrequested block: %s (%s).',
|
'Received unrequested block: %s (%s).',
|
||||||
block.rhash, peer.hostname);
|
block.rhash, peer.hostname);
|
||||||
return yield utils.wait();
|
return yield spawn.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -1062,7 +1062,7 @@ Pool.prototype.createPeer = function createPeer(addr, socket) {
|
|||||||
self.startInterval();
|
self.startInterval();
|
||||||
self.startTimeout();
|
self.startTimeout();
|
||||||
}
|
}
|
||||||
}).catch(function(err) {
|
}, function(err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1081,7 +1081,7 @@ Pool.prototype.createPeer = function createPeer(addr, socket) {
|
|||||||
self.startInterval();
|
self.startInterval();
|
||||||
self.startTimeout();
|
self.startTimeout();
|
||||||
}
|
}
|
||||||
}).catch(function(err) {;
|
}, function(err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,8 +10,8 @@ var utils = require('../utils/utils');
|
|||||||
var spawn = require('../utils/spawn');
|
var spawn = require('../utils/spawn');
|
||||||
var co = spawn.co;
|
var co = spawn.co;
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
|
var wait = spawn.wait;
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var wait = utils.wait;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract object that handles state and
|
* An abstract object that handles state and
|
||||||
|
|||||||
@ -1,5 +1,20 @@
|
|||||||
|
/*!
|
||||||
|
* spawn.js - promise and generator control flow for bcoin
|
||||||
|
* Originally based on yoursnetwork's "asink" module.
|
||||||
|
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||||
|
* https://github.com/bcoin-org/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var utils = require('./utils');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an instantiated generator.
|
||||||
|
* @param {Generator} gen
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
function exec(gen) {
|
function exec(gen) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
function step(value, rejection) {
|
function step(value, rejection) {
|
||||||
@ -34,11 +49,27 @@ function exec(gen) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute generator function
|
||||||
|
* with a context and execute.
|
||||||
|
* @param {GeneratorFunction} generator
|
||||||
|
* @param {Object} self
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
function spawn(generator, self) {
|
function spawn(generator, self) {
|
||||||
var gen = generator.call(self);
|
var gen = generator.call(self);
|
||||||
return exec(gen);
|
return exec(gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a generator function to be
|
||||||
|
* executed into a function that
|
||||||
|
* returns a promise.
|
||||||
|
* @param {GeneratorFunction}
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
|
||||||
function co(generator) {
|
function co(generator) {
|
||||||
return function() {
|
return function() {
|
||||||
var gen = generator.apply(this, arguments);
|
var gen = generator.apply(this, arguments);
|
||||||
@ -46,6 +77,157 @@ function co(generator) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
spawn.co = co;
|
/**
|
||||||
|
* Wrap a generator function to be
|
||||||
|
* executed into a function that
|
||||||
|
* accepts a node.js style callback.
|
||||||
|
* @param {GeneratorFunction}
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function cob(generator) {
|
||||||
|
return function() {
|
||||||
|
var i, args, callback, gen;
|
||||||
|
|
||||||
|
if (arguments.length === 0
|
||||||
|
|| typeof arguments[arguments.length - 1] !== 'function') {
|
||||||
|
throw new Error('Function must accept a callback.');
|
||||||
|
}
|
||||||
|
|
||||||
|
args = new Array(arguments.length - 1);
|
||||||
|
callback = arguments[arguments.length - 1];
|
||||||
|
|
||||||
|
for (i = 0; i < args.length; i++)
|
||||||
|
args[i] = arguments[i];
|
||||||
|
|
||||||
|
gen = generator.apply(this, args);
|
||||||
|
|
||||||
|
return cb(exec(gen), callback);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for promise to resolve and
|
||||||
|
* execute a node.js style callback.
|
||||||
|
* @param {Promise} promise
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
function cb(promise, callback) {
|
||||||
|
promise.then(function(value) {
|
||||||
|
callback(null, value);
|
||||||
|
}, function(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for a nextTick with a promise.
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function wait() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
utils.nextTick(resolve);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for a timeout with a promise.
|
||||||
|
* @param {Number} time
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function timeout(time) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
setTimeout(function() {
|
||||||
|
resolve();
|
||||||
|
}, time);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap `resolve` and `reject` into
|
||||||
|
* a node.js style callback.
|
||||||
|
* @param {Function} resolve
|
||||||
|
* @param {Function} reject
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function wrap(resolve, reject) {
|
||||||
|
return function(err, result) {
|
||||||
|
if (err)
|
||||||
|
return reject(err);
|
||||||
|
resolve(result);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call a function that accepts node.js
|
||||||
|
* style callbacks, wrap with a promise.
|
||||||
|
* @param {Function} func
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function call(func) {
|
||||||
|
var args = new Array(Math.max(0, arguments.length - 1));
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i = 1; i < arguments.length; i++)
|
||||||
|
args[i] = arguments[i];
|
||||||
|
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
args.push(function(err, result) {
|
||||||
|
if (err)
|
||||||
|
return reject(err);
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
func.apply(self, args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a function that accepts node.js
|
||||||
|
* style callbacks into a function that
|
||||||
|
* returns a promise.
|
||||||
|
* @param {Function} func
|
||||||
|
* @param {Object?} self
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function promisify(func, self) {
|
||||||
|
return function() {
|
||||||
|
var args = new Array(arguments.length);
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i = 0; i < args.length; i++)
|
||||||
|
args[i] = arguments[i];
|
||||||
|
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
args.push(function(err, result) {
|
||||||
|
if (err)
|
||||||
|
return reject(err);
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
func.apply(self, args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expose
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports = spawn;
|
||||||
|
exports.exec = exec;
|
||||||
|
exports.spawn = spawn;
|
||||||
|
exports.co = co;
|
||||||
|
exports.cob = cob;
|
||||||
|
exports.cb = cb;
|
||||||
|
exports.wait = wait;
|
||||||
|
exports.timeout = timeout;
|
||||||
|
exports.wrap = wrap;
|
||||||
|
exports.call = call;
|
||||||
|
exports.promisify = promisify;
|
||||||
|
|
||||||
module.exports = spawn;
|
module.exports = spawn;
|
||||||
|
|||||||
@ -326,28 +326,6 @@ if (typeof setImmediate === 'function') {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.wait = function wait() {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
utils.nextTick(resolve);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
utils.timeout = function timeout(time) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
setTimeout(function() {
|
|
||||||
resolve();
|
|
||||||
}, time);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
utils.P = function P(resolve, reject) {
|
|
||||||
return function(err, result) {
|
|
||||||
if (err)
|
|
||||||
return reject(err);
|
|
||||||
resolve(result);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap a function in a `nextTick`.
|
* Wrap a function in a `nextTick`.
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
|
|||||||
@ -576,7 +576,7 @@ Worker.prototype._execute = function _execute(method, args, timeout, callback) {
|
|||||||
Worker.prototype.execute = function execute(method, args, timeout) {
|
Worker.prototype.execute = function execute(method, args, timeout) {
|
||||||
var self = this;
|
var self = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self._execute(method, args, timeout, utils.P(resolve, reject));
|
self._execute(method, args, timeout, spawn.wrap(resolve, reject));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ var utils = bcoin.utils;
|
|||||||
var crypto = require('../lib/crypto/crypto');
|
var crypto = require('../lib/crypto/crypto');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var opcodes = constants.opcodes;
|
var opcodes = constants.opcodes;
|
||||||
|
var spawn = require('../lib/utils/spawn');
|
||||||
|
var c = require('../lib/utils/spawn').cb;
|
||||||
|
|
||||||
describe('Chain', function() {
|
describe('Chain', function() {
|
||||||
var chain, wallet, node, miner, walletdb;
|
var chain, wallet, node, miner, walletdb;
|
||||||
@ -14,22 +16,6 @@ describe('Chain', function() {
|
|||||||
|
|
||||||
this.timeout(5000);
|
this.timeout(5000);
|
||||||
|
|
||||||
function c(p, cb) {
|
|
||||||
var called = false;
|
|
||||||
p.then(function(result) {
|
|
||||||
called = true;
|
|
||||||
cb(null, result);
|
|
||||||
}).catch(function(err) {
|
|
||||||
if (called) {
|
|
||||||
utils.nextTick(function() {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
node = new bcoin.fullnode({ db: 'memory' });
|
node = new bcoin.fullnode({ db: 'memory' });
|
||||||
chain = node.chain;
|
chain = node.chain;
|
||||||
walletdb = node.walletdb;
|
walletdb = node.walletdb;
|
||||||
@ -250,7 +236,7 @@ describe('Chain', function() {
|
|||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
c(chain.db.scan(null, hashes, function *(block, txs) {
|
c(chain.db.scan(null, hashes, function *(block, txs) {
|
||||||
total += txs.length;
|
total += txs.length;
|
||||||
yield utils.wait();
|
yield spawn.wait();
|
||||||
}), function(err) {
|
}), function(err) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.equal(total, 25);
|
assert.equal(total, 25);
|
||||||
|
|||||||
@ -8,6 +8,7 @@ var utils = bcoin.utils;
|
|||||||
var crypto = require('../lib/crypto/crypto');
|
var crypto = require('../lib/crypto/crypto');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var scriptTypes = constants.scriptTypes;
|
var scriptTypes = constants.scriptTypes;
|
||||||
|
var c = require('../lib/utils/spawn').cb;
|
||||||
|
|
||||||
var dummyInput = {
|
var dummyInput = {
|
||||||
prevout: {
|
prevout: {
|
||||||
@ -28,22 +29,6 @@ var dummyInput = {
|
|||||||
sequence: 0xffffffff
|
sequence: 0xffffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
function c(p, cb) {
|
|
||||||
var called = false;
|
|
||||||
p.then(function(result) {
|
|
||||||
called = true;
|
|
||||||
cb(null, result);
|
|
||||||
}).catch(function(err) {
|
|
||||||
if (called) {
|
|
||||||
utils.nextTick(function() {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('HTTP', function() {
|
describe('HTTP', function() {
|
||||||
var request = bcoin.http.request;
|
var request = bcoin.http.request;
|
||||||
var w, addr, hash;
|
var w, addr, hash;
|
||||||
|
|||||||
@ -7,22 +7,7 @@ var utils = bcoin.utils;
|
|||||||
var crypto = require('../lib/crypto/crypto');
|
var crypto = require('../lib/crypto/crypto');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var opcodes = constants.opcodes;
|
var opcodes = constants.opcodes;
|
||||||
|
var c = require('../lib/utils/spawn').cb;
|
||||||
function c(p, cb) {
|
|
||||||
var called = false;
|
|
||||||
p.then(function(result) {
|
|
||||||
called = true;
|
|
||||||
cb(null, result);
|
|
||||||
}).catch(function(err) {
|
|
||||||
if (called) {
|
|
||||||
utils.nextTick(function() {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Mempool', function() {
|
describe('Mempool', function() {
|
||||||
this.timeout(5000);
|
this.timeout(5000);
|
||||||
|
|||||||
@ -9,6 +9,7 @@ var crypto = require('../lib/crypto/crypto');
|
|||||||
var spawn = require('../lib/utils/spawn');
|
var spawn = require('../lib/utils/spawn');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var scriptTypes = constants.scriptTypes;
|
var scriptTypes = constants.scriptTypes;
|
||||||
|
var c = require('../lib/utils/spawn').cb;
|
||||||
|
|
||||||
var FAKE_SIG = new Buffer([0,0,0,0,0,0,0,0,0]);
|
var FAKE_SIG = new Buffer([0,0,0,0,0,0,0,0,0]);
|
||||||
|
|
||||||
@ -53,22 +54,6 @@ assert.range = function range(value, lo, hi, message) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function c(p, cb) {
|
|
||||||
var called = false;
|
|
||||||
p.then(function(result) {
|
|
||||||
called = true;
|
|
||||||
cb(null, result);
|
|
||||||
}).catch(function(err) {
|
|
||||||
if (called) {
|
|
||||||
utils.nextTick(function() {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Wallet', function() {
|
describe('Wallet', function() {
|
||||||
var walletdb = new bcoin.walletdb({
|
var walletdb = new bcoin.walletdb({
|
||||||
name: 'wallet-test',
|
name: 'wallet-test',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user