walletdb improvements. start refactoring node object.
This commit is contained in:
parent
c41ded7360
commit
00b8f8950b
8
bin/node
8
bin/node
@ -4,10 +4,16 @@ var bcoin = require('bcoin');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
|
||||
var node = bcoin.node({
|
||||
var node = bcoin.fullnode({
|
||||
debug: true
|
||||
});
|
||||
|
||||
node.on('error', function(err) {
|
||||
utils.print(err.message);
|
||||
});
|
||||
|
||||
node.pool.on('full', function() {
|
||||
setInterval(function() {
|
||||
console.log(node.wallet.getAll());
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
@ -76,8 +76,9 @@ bcoin.merkleblock = require('./bcoin/merkleblock');
|
||||
bcoin.headers = require('./bcoin/headers');
|
||||
bcoin.ramdisk = require('./bcoin/ramdisk');
|
||||
bcoin.blockdb = require('./bcoin/blockdb');
|
||||
bcoin.node = require('./bcoin/node2');
|
||||
bcoin.spvnode = require('./bcoin/spvnode');
|
||||
bcoin.node = require('./bcoin/node');
|
||||
bcoin.fullnode = require('./bcoin/node');
|
||||
bcoin.chainblock = require('./bcoin/chainblock');
|
||||
bcoin.chaindb = require('./bcoin/chaindb');
|
||||
bcoin.chain = require('./bcoin/chain');
|
||||
|
||||
@ -15,12 +15,17 @@ var fs = bcoin.fs;
|
||||
* BlockDB
|
||||
*/
|
||||
|
||||
function BlockDB(options) {
|
||||
function BlockDB(node, options) {
|
||||
var self = this;
|
||||
var levelup;
|
||||
|
||||
if (!(this instanceof BlockDB))
|
||||
return new BlockDB(options);
|
||||
return new BlockDB(node, options);
|
||||
|
||||
if (!(node instanceof bcoin.node)) {
|
||||
options = node;
|
||||
node = null;
|
||||
}
|
||||
|
||||
// Some lazy loading
|
||||
levelup = require('levelup');
|
||||
@ -39,6 +44,7 @@ function BlockDB(options) {
|
||||
|
||||
this.options = options;
|
||||
|
||||
this.node = node;
|
||||
this.data = new BlockData(options);
|
||||
|
||||
this.cache = {
|
||||
@ -1023,10 +1029,10 @@ BlockDB.prototype.resetHeight = function resetHeight(height, callback, emit) {
|
||||
};
|
||||
|
||||
BlockDB.prototype._getEntry = function _getEntry(height, callback) {
|
||||
if (!bcoin.chain.global)
|
||||
if (!this.node)
|
||||
return callback();
|
||||
|
||||
return bcoin.chain.global.db.getAsync(height, callback);
|
||||
return this.node.chain.db.getAsync(height, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -18,9 +18,9 @@ var fs = bcoin.fs;
|
||||
* Chain
|
||||
*/
|
||||
|
||||
function Chain(options) {
|
||||
function Chain(node, options) {
|
||||
if (!(this instanceof Chain))
|
||||
return new Chain(options);
|
||||
return new Chain(node, options);
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
@ -35,8 +35,9 @@ function Chain(options) {
|
||||
this.db = new bcoin.chaindb(this);
|
||||
this.request = new utils.RequestCache();
|
||||
this.loading = false;
|
||||
this.mempool = options.mempool;
|
||||
this.blockdb = options.blockdb;
|
||||
this.node = node;
|
||||
this.mempool = node.mempool;
|
||||
this.blockdb = node.blockdb;
|
||||
this.busy = false;
|
||||
this.jobs = [];
|
||||
this.pending = [];
|
||||
|
||||
@ -69,8 +69,10 @@ HTTPServer.prototype._init = function _init() {
|
||||
self.node.getCoinByAddress(addresses, function(err, coins) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!coins.length)
|
||||
return send(404);
|
||||
|
||||
send(200, coins.map(function(coin) { return coin.toJSON(); }));
|
||||
});
|
||||
});
|
||||
@ -81,8 +83,10 @@ HTTPServer.prototype._init = function _init() {
|
||||
self.node.getCoin(req.params.hash, +req.params.index, function(err, coin) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!coin)
|
||||
return send(404);
|
||||
|
||||
send(200, coin.toJSON());
|
||||
});
|
||||
});
|
||||
@ -92,8 +96,10 @@ HTTPServer.prototype._init = function _init() {
|
||||
self.node.getCoinByAddress(req.body.addresses, function(err, coins) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!coins.length)
|
||||
return send(404);
|
||||
|
||||
send(200, coins.map(function(coin) { return coin.toJSON(); }));
|
||||
});
|
||||
});
|
||||
@ -104,8 +110,10 @@ HTTPServer.prototype._init = function _init() {
|
||||
self.node.getTX(req.params.hash, function(err, tx) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!tx)
|
||||
return send(404);
|
||||
|
||||
send(200, tx.toJSON());
|
||||
});
|
||||
});
|
||||
@ -116,8 +124,10 @@ HTTPServer.prototype._init = function _init() {
|
||||
self.node.getTXByAddress(addresses, function(err, txs) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!txs.length)
|
||||
return send(404);
|
||||
|
||||
send(200, txs.map(function(tx) { return tx.toJSON(); }));
|
||||
});
|
||||
});
|
||||
@ -145,8 +155,10 @@ HTTPServer.prototype._init = function _init() {
|
||||
self.node.getBlock(hash, function(err, block) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!block)
|
||||
return send(404);
|
||||
|
||||
send(200, block.toJSON());
|
||||
});
|
||||
});
|
||||
@ -156,8 +168,10 @@ HTTPServer.prototype._init = function _init() {
|
||||
self.node.walletdb.getJSON(req.params.id, function(err, json) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!json)
|
||||
return send(404);
|
||||
|
||||
send(200, json);
|
||||
});
|
||||
});
|
||||
@ -165,33 +179,71 @@ HTTPServer.prototype._init = function _init() {
|
||||
// Create/get wallet
|
||||
this.post('/wallet/:id', function(req, res, next, send) {
|
||||
req.body.id = req.params.id;
|
||||
self.node.walletdb.create(req.body, function(err, json) {
|
||||
self.node.walletdb.createJSON(req.body.id, req.body, function(err, json) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!json)
|
||||
return send(404);
|
||||
send(json);
|
||||
|
||||
send(200, json);
|
||||
});
|
||||
});
|
||||
|
||||
// Update wallet / sync address depth
|
||||
this.put('/wallet/:id', function(req, res, next, send) {
|
||||
req.body.id = req.params.id;
|
||||
self.node.walletdb.save(req.body.id, req.body, function(err, json) {
|
||||
self.node.walletdb.saveJSON(req.body.id, req.body, function(err, json) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!json)
|
||||
return send(404);
|
||||
send(json);
|
||||
|
||||
send(200, json);
|
||||
});
|
||||
});
|
||||
|
||||
// Wallet UTXOs
|
||||
this.get('/wallet/:id/utxo', function(req, res, next) {
|
||||
this.get('/wallet/:id/utxo', function(req, res, next, send) {
|
||||
self.node.walletdb.getJSON(req.params.id, function(err, json) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!json)
|
||||
return send(404);
|
||||
|
||||
self.node.getCoinByAddress(Object.keys(json.addressMap), function(err, coins) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!coins.length)
|
||||
return send(404);
|
||||
|
||||
send(200, coins.map(function(coin) { return coin.toJSON(); }));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Wallet TXs
|
||||
this.get('/wallet/:id/tx', function(req, res, next) {
|
||||
this.get('/wallet/:id/tx', function(req, res, next, send) {
|
||||
self.node.walletdb.getJSON(req.params.id, function(err, json) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!json)
|
||||
return send(404);
|
||||
|
||||
self.node.getTXByAddress(Object.keys(json.addressMap), function(err, txs) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!txs.length)
|
||||
return send(404);
|
||||
|
||||
send(200, coins.map(function(tx) { return tx.toJSON(); }));
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ var fs = bcoin.fs;
|
||||
|
||||
function Mempool(node, options) {
|
||||
if (!(this instanceof Mempool))
|
||||
return new Mempool(pool, options);
|
||||
return new Mempool(node, options);
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
@ -16,9 +16,9 @@ var EventEmitter = require('events').EventEmitter;
|
||||
* Miner
|
||||
*/
|
||||
|
||||
function Miner(pool, options) {
|
||||
function Miner(node, options) {
|
||||
if (!(this instanceof Miner))
|
||||
return new Miner(options);
|
||||
return new Miner(node, options);
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
@ -27,19 +27,19 @@ function Miner(pool, options) {
|
||||
|
||||
this.options = options;
|
||||
this.address = this.options.address;
|
||||
this.msg = this.options.msg || 'mined by bcoin';
|
||||
this.coinbaseFlags = this.options.coinbaseFlags || 'mined by bcoin';
|
||||
|
||||
this.pool = pool || bcoin.pool.global;
|
||||
this.chain = this.pool.chain;
|
||||
this.mempool = this.pool.mempool;
|
||||
this.blockdb = this.pool.blockdb;
|
||||
this.node = node;
|
||||
this.pool = node.pool;
|
||||
this.chain = node.chain;
|
||||
this.mempool = node.mempool;
|
||||
|
||||
this.running = false;
|
||||
this.timeout = null;
|
||||
this.interval = null;
|
||||
|
||||
this.fee = new bn(0);
|
||||
this.last = this.chain.tip;
|
||||
this.last = this.node.chain.tip;
|
||||
this.block = null;
|
||||
this.iterations = 0;
|
||||
this._begin = utils.now();
|
||||
@ -229,7 +229,7 @@ Miner.prototype.createBlock = function createBlock(tx) {
|
||||
new Buffer(utils.nonce().toArray()),
|
||||
// Let the world know this little
|
||||
// miner succeeded.
|
||||
new Buffer(this.msg || 'mined by bcoin', 'ascii')
|
||||
new Buffer(this.coinbaseFlags || 'mined by bcoin', 'ascii')
|
||||
],
|
||||
sequence: 0xffffffff
|
||||
});
|
||||
|
||||
@ -699,6 +699,9 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) {
|
||||
|
||||
if (bcoin.script.isWitnessProgram(prev)) {
|
||||
witness = true;
|
||||
// Now calculating vsize. The regular
|
||||
// redeem script (if there was one)
|
||||
// is now worth 4 points.
|
||||
size *= 4;
|
||||
if (this.inputs[i].witness.length && bcoin.script.isWitnessScripthash(prev)) {
|
||||
prev = this.inputs[i].witness[this.inputs[i].witness.length - 1];
|
||||
@ -763,9 +766,10 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) {
|
||||
}
|
||||
}
|
||||
|
||||
// Byte for varint size of input script
|
||||
// Byte for varint size of input script.
|
||||
size += utils.sizeIntv(size);
|
||||
|
||||
// Calculate vsize if we're a witness program.
|
||||
if (witness)
|
||||
size = (size + 3) / 4 | 0;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* node.js - full node for bcoin
|
||||
* fullnode.js - full node for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* https://github.com/indutny/bcoin
|
||||
*/
|
||||
@ -14,68 +14,66 @@ var assert = utils.assert;
|
||||
var fs = bcoin.fs;
|
||||
|
||||
/**
|
||||
* Node
|
||||
* Fullnode
|
||||
*/
|
||||
|
||||
function Node(options) {
|
||||
if (!(this instanceof Node))
|
||||
return new Node(options);
|
||||
function Fullnode(options) {
|
||||
if (!(this instanceof Fullnode))
|
||||
return new Fullnode(options);
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
this.options = options;
|
||||
bcoin.node.call(this, options);
|
||||
|
||||
if (this.options.debug)
|
||||
bcoin.debug = this.options.debug;
|
||||
this.options.http = {};
|
||||
|
||||
if (this.options.network)
|
||||
network.set(this.options.network);
|
||||
if (!this.options.wallet)
|
||||
this.options.wallet = {};
|
||||
|
||||
this.blockdb = null;
|
||||
this.mempool = null;
|
||||
this.pool = null;
|
||||
this.chain = null;
|
||||
this.miner = null;
|
||||
this.wallet = null;
|
||||
if (!this.options.wallet.id)
|
||||
this.options.wallet.id = 'primary';
|
||||
|
||||
if (!this.options.wallet.passphrase)
|
||||
this.options.wallet.passphrase = 'node';
|
||||
|
||||
this.loading = false;
|
||||
|
||||
Node.global = this;
|
||||
Fullnode.global = this;
|
||||
|
||||
this._init();
|
||||
}
|
||||
|
||||
utils.inherits(Node, EventEmitter);
|
||||
utils.inherits(Fullnode, bcoin.node);
|
||||
|
||||
Node.prototype._init = function _init() {
|
||||
Fullnode.prototype._init = function _init() {
|
||||
var self = this;
|
||||
|
||||
this.loading = true;
|
||||
|
||||
if (!this.options.pool)
|
||||
this.options.pool = {};
|
||||
// BlockDB and Mempool need to be instantiated
|
||||
// first because the chain needs access to them.
|
||||
this.blockdb = new bcoin.blockdb(this, {
|
||||
cache: false
|
||||
});
|
||||
|
||||
if (!this.options.miner)
|
||||
this.options.miner = {};
|
||||
this.mempool = new bcoin.mempool(this);
|
||||
|
||||
this.blockdb = new bcoin.blockdb(this.options.blockdb);
|
||||
this.mempool = new bcoin.mempool(this, this.options.mempool);
|
||||
// Chain is instantiated next. The pool needs it.
|
||||
this.chain = new bcoin.chain(this, {
|
||||
preload: false
|
||||
});
|
||||
|
||||
this.options.pool.spv = false;
|
||||
this.options.pool.blockdb = this.blockdb;
|
||||
this.options.pool.mempool = this.mempool;
|
||||
this.pool = new bcoin.pool(this, {
|
||||
witness: this.network.type === 'segnet',
|
||||
spv: false
|
||||
});
|
||||
|
||||
this.pool = new bcoin.pool(this.options.pool);
|
||||
this.chain = this.pool.chain;
|
||||
this.miner = new bcoin.miner(this, this.options.miner);
|
||||
this.walletdb = new bcoin.walletdb(this, this.options.walletdb);
|
||||
|
||||
this.miner = new bcoin.miner(this.pool, this.options.miner);
|
||||
|
||||
this.walletdb = new bcoin.walletdb(this.options.walletdb);
|
||||
|
||||
this.options.http = {};
|
||||
if (this.options.http && bcoin.http) {
|
||||
this.http = new bcoin.http(this, this.options.http);
|
||||
this.http.listen(this.options.http.port || 8080);
|
||||
@ -89,61 +87,79 @@ Node.prototype._init = function _init() {
|
||||
self.emit('error', err);
|
||||
});
|
||||
|
||||
if (!this.options.wallet)
|
||||
this.options.wallet = {};
|
||||
this.on('tx', function(tx) {
|
||||
self.walletdb.ownTX(tx, function(err, input, output) {
|
||||
if (err)
|
||||
return self.emit('error', err);
|
||||
|
||||
if (!this.options.wallet.id)
|
||||
this.options.wallet.id = 'primary';
|
||||
self.emit('own tx', tx, input, output);
|
||||
});
|
||||
});
|
||||
|
||||
if (!this.options.wallet.passphrase)
|
||||
this.options.wallet.passphrase = 'node';
|
||||
this.chain.on('block', function(block) {
|
||||
self.emit('block', block);
|
||||
block.txs.forEach(function(tx) {
|
||||
self.emit('tx', tx, block);
|
||||
});
|
||||
});
|
||||
|
||||
this.walletdb.create(this.options.wallet, function(err, wallet) {
|
||||
this.mempool.on('tx', function(tx) {
|
||||
self.emit('tx', tx);
|
||||
});
|
||||
|
||||
// Handle forks
|
||||
this.chain.on('remove entry', function(entry) {
|
||||
self.wallets.forEach(function(wallet) {
|
||||
wallet.tx.getAll().forEach(function(tx) {
|
||||
if (tx.block === entry.hash || tx.height >= entry.height)
|
||||
wallet.tx.unconfirm(tx);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.createWallet(this.options.wallet, function(err, wallet) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
self.wallet = wallet;
|
||||
self.miner.address = wallet.getAddress();
|
||||
|
||||
self.pool.startSync();
|
||||
|
||||
self.loading = false;
|
||||
self.emit('load');
|
||||
});
|
||||
};
|
||||
|
||||
Fullnode.prototype.createWallet = function createWallet(options, callback) {
|
||||
var self = this;
|
||||
callback = utils.ensure(callback);
|
||||
this.walletdb.create(options, function(err, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
assert(wallet);
|
||||
|
||||
utils.debug('Loaded wallet with id=%s address=%s',
|
||||
wallet.getID(), wallet.getAddress());
|
||||
|
||||
self.chain.on('block', function(block) {
|
||||
block.txs.forEach(function(tx) {
|
||||
self.wallet.addTX(tx);
|
||||
});
|
||||
});
|
||||
self.wallets.push(wallet);
|
||||
|
||||
self.mempool.on('tx', function(tx) {
|
||||
self.wallet.addTX(tx);
|
||||
});
|
||||
return callback(null, wallet);
|
||||
|
||||
self.miner.address = self.wallet.getAddress();
|
||||
|
||||
// Handle forks
|
||||
self.chain.on('remove entry', function(entry) {
|
||||
self.wallet.tx.getAll().forEach(function(tx) {
|
||||
if (tx.block === entry.hash || tx.height >= entry.height)
|
||||
self.wallet.tx.unconfirm(tx);
|
||||
});
|
||||
});
|
||||
|
||||
self.pool.addWallet(self.wallet, function(err) {
|
||||
self.pool.addWallet(wallet, function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
return callback(err);
|
||||
|
||||
self.pool.startSync();
|
||||
|
||||
self.loading = false;
|
||||
self.emit('load');
|
||||
return callback(null, wallet);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Node.prototype.scanWallet = function scanWallet(callback) {
|
||||
this.wallet.scan(this.getTXByAddress.bind(this), callback);
|
||||
Fullnode.prototype.scanWallet = function scanWallet(wallet, callback) {
|
||||
wallet.scan(this.getTXByAddress.bind(this), callback);
|
||||
};
|
||||
|
||||
Node.prototype.getBlock = function getBlock(hash, callback) {
|
||||
Fullnode.prototype.getBlock = function getBlock(hash, callback) {
|
||||
var self = this;
|
||||
var coin;
|
||||
|
||||
@ -158,7 +174,7 @@ Node.prototype.getBlock = function getBlock(hash, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Node.prototype.getCoin = function getCoin(hash, index, callback) {
|
||||
Fullnode.prototype.getCoin = function getCoin(hash, index, callback) {
|
||||
var self = this;
|
||||
var coin;
|
||||
|
||||
@ -182,7 +198,7 @@ Node.prototype.getCoin = function getCoin(hash, index, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Node.prototype.getCoinByAddress = function getCoinByAddress(addresses, callback) {
|
||||
Fullnode.prototype.getCoinByAddress = function getCoinByAddress(addresses, callback) {
|
||||
var self = this;
|
||||
var mempool;
|
||||
|
||||
@ -202,7 +218,7 @@ Node.prototype.getCoinByAddress = function getCoinByAddress(addresses, callback)
|
||||
});
|
||||
};
|
||||
|
||||
Node.prototype.getTX = function getTX(hash, callback) {
|
||||
Fullnode.prototype.getTX = function getTX(hash, callback) {
|
||||
var self = this;
|
||||
var tx;
|
||||
|
||||
@ -223,7 +239,7 @@ Node.prototype.getTX = function getTX(hash, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Node.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||
Fullnode.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||
var self = this;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
@ -234,7 +250,7 @@ Node.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||
this.blockdb.isSpent(hash, index, callback);
|
||||
};
|
||||
|
||||
Node.prototype.getTXByAddress = function getTXByAddress(addresses, callback) {
|
||||
Fullnode.prototype.getTXByAddress = function getTXByAddress(addresses, callback) {
|
||||
var self = this;
|
||||
var mempool;
|
||||
|
||||
@ -250,7 +266,7 @@ Node.prototype.getTXByAddress = function getTXByAddress(addresses, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Node.prototype.fillCoin = function fillCoin(tx, callback) {
|
||||
Fullnode.prototype.fillCoin = function fillCoin(tx, callback) {
|
||||
callback = utils.asyncify(callback);
|
||||
|
||||
if (this.mempool.fillCoin(tx))
|
||||
@ -259,7 +275,7 @@ Node.prototype.fillCoin = function fillCoin(tx, callback) {
|
||||
this.blockdb.fillCoin(tx, callback);
|
||||
};
|
||||
|
||||
Node.prototype.fillTX = function fillTX(tx, callback) {
|
||||
Fullnode.prototype.fillTX = function fillTX(tx, callback) {
|
||||
callback = utils.asyncify(callback);
|
||||
|
||||
if (this.mempool.fillTX(tx))
|
||||
@ -272,4 +288,4 @@ Node.prototype.fillTX = function fillTX(tx, callback) {
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Node;
|
||||
module.exports = Fullnode;
|
||||
|
||||
54
lib/bcoin/node2.js
Normal file
54
lib/bcoin/node2.js
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* node.js - node object for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* https://github.com/indutny/bcoin
|
||||
*/
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var bcoin = require('../bcoin');
|
||||
var bn = require('bn.js');
|
||||
var constants = bcoin.protocol.constants;
|
||||
var network = bcoin.protocol.network;
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var fs = bcoin.fs;
|
||||
|
||||
/**
|
||||
* Node
|
||||
*/
|
||||
|
||||
function Node(options) {
|
||||
if (!(this instanceof Node))
|
||||
return new Node(options);
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
this.options = options;
|
||||
|
||||
if (this.options.debug)
|
||||
bcoin.debug = this.options.debug;
|
||||
|
||||
if (this.options.network)
|
||||
network.set(this.options.network);
|
||||
|
||||
this.network = network;
|
||||
this.blockdb = null;
|
||||
this.mempool = null;
|
||||
this.pool = null;
|
||||
this.chain = null;
|
||||
this.miner = null;
|
||||
this.wallets = [];
|
||||
|
||||
Node.global = this;
|
||||
}
|
||||
|
||||
utils.inherits(Node, EventEmitter);
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Node;
|
||||
@ -16,12 +16,12 @@ var constants = bcoin.protocol.constants;
|
||||
* Pool
|
||||
*/
|
||||
|
||||
function Pool(options) {
|
||||
function Pool(node, options) {
|
||||
var self = this;
|
||||
var Chain;
|
||||
|
||||
if (!(this instanceof Pool))
|
||||
return new Pool(options);
|
||||
return new Pool(node, options);
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
@ -55,8 +55,9 @@ function Pool(options) {
|
||||
this.destroyed = false;
|
||||
this.size = options.size || 8;
|
||||
|
||||
this.blockdb = options.blockdb;
|
||||
this.mempool = options.mempool;
|
||||
this.chain = node.chain;
|
||||
this.blockdb = node.blockdb;
|
||||
this.mempool = node.mempool;
|
||||
|
||||
if (options.spv) {
|
||||
if (options.headers == null)
|
||||
@ -76,12 +77,12 @@ function Pool(options) {
|
||||
|
||||
this.requestTimeout = options.requestTimeout || 2 * 60000;
|
||||
|
||||
this.chain = new bcoin.chain({
|
||||
spv: options.spv,
|
||||
preload: options.preload,
|
||||
blockdb: options.blockdb,
|
||||
mempool: options.mempool
|
||||
});
|
||||
// this.chain = new bcoin.chain({
|
||||
// spv: options.spv,
|
||||
// preload: options.preload,
|
||||
// blockdb: options.blockdb,
|
||||
// mempool: options.mempool
|
||||
// });
|
||||
|
||||
this.watchMap = {};
|
||||
|
||||
@ -118,7 +119,7 @@ function Pool(options) {
|
||||
type: 'tx'
|
||||
};
|
||||
|
||||
if (network.type === 'segnet') {
|
||||
if (this.options.witness) {
|
||||
this.block.type = 'witness' + this.block.type;
|
||||
this.tx.type = 'witness' + this.tx.type;
|
||||
}
|
||||
|
||||
@ -465,6 +465,57 @@ TX.prototype.getFunds = function getFunds(side) {
|
||||
return this.getOutputValue();
|
||||
};
|
||||
|
||||
TX.prototype.getInputAddresses = function getInputAddresses() {
|
||||
var table = {};
|
||||
var addresses = [];
|
||||
var i, address;
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
address = this.inputs[i].getAddress();
|
||||
if (address && !table[address]) {
|
||||
table[address] = true;
|
||||
addresses.push(address);
|
||||
}
|
||||
}
|
||||
|
||||
addresses.table = table;
|
||||
|
||||
return addresses;
|
||||
};
|
||||
|
||||
TX.prototype.getOutputAddresses = function getOutputAddresses() {
|
||||
var table = {};
|
||||
var addresses = [];
|
||||
var i, address;
|
||||
|
||||
for (i = 0; i < this.outputs.length; i++) {
|
||||
address = this.outputs[i].getAddress();
|
||||
if (address && !table[address]) {
|
||||
table[address] = true;
|
||||
addresses.push(address);
|
||||
}
|
||||
}
|
||||
|
||||
addresses.table = table;
|
||||
|
||||
return addresses;
|
||||
};
|
||||
|
||||
TX.prototype.getAddresses = function getAddresses() {
|
||||
var input = this.getInputAddresses();
|
||||
var output = this.getOutputAddresses();
|
||||
var i;
|
||||
|
||||
for (i = 0; i < output.length; i++) {
|
||||
if (!input.table[output[i]]) {
|
||||
input.table[output[i]] = true;
|
||||
input.push(output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
};
|
||||
|
||||
TX.prototype.testInputs = function testInputs(addressTable, index) {
|
||||
var i, input;
|
||||
|
||||
|
||||
@ -415,6 +415,14 @@ utils.asyncify = function asyncify(callback) {
|
||||
return asyncifyFn;
|
||||
};
|
||||
|
||||
utils.nop = function() {};
|
||||
|
||||
utils.ensure = function ensure(callback) {
|
||||
if (!callback)
|
||||
return utils.nop;
|
||||
return callback;
|
||||
};
|
||||
|
||||
utils.revHex = function revHex(s) {
|
||||
var r = '';
|
||||
var i = 0;
|
||||
|
||||
@ -373,12 +373,17 @@ Wallet.prototype.deriveAddress = function deriveAddress(change, index) {
|
||||
address = new bcoin.address(options);
|
||||
|
||||
this.addressMap[address.getKeyAddress()] = data.path;
|
||||
this._saveAddress(address.getKeyAddress());
|
||||
|
||||
if (this.type === 'multisig')
|
||||
if (this.type === 'multisig') {
|
||||
this.addressMap[address.getScriptAddress()] = data.path;
|
||||
this._saveAddress(address.getScriptAddress());
|
||||
}
|
||||
|
||||
if (this.witness)
|
||||
if (this.witness) {
|
||||
this.addressMap[address.getProgramAddress()] = data.path;
|
||||
this._saveAddress(address.getProgramAddress());
|
||||
}
|
||||
|
||||
this.emit('add address', address);
|
||||
|
||||
@ -876,7 +881,7 @@ Wallet.prototype.__defineGetter__('address', function() {
|
||||
return this.getAddress();
|
||||
});
|
||||
|
||||
Wallet.prototype.toJSON = function toJSON(noPool) {
|
||||
Wallet.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
v: 3,
|
||||
name: 'wallet',
|
||||
@ -897,7 +902,7 @@ Wallet.prototype.toJSON = function toJSON(noPool) {
|
||||
return key.xpubkey;
|
||||
}),
|
||||
balance: utils.btc(this.getBalance()),
|
||||
txs: noPool ? [] : this.tx.getAll().map(function(tx) {
|
||||
txs: this.options.noPool ? [] : this.tx.getAll().map(function(tx) {
|
||||
return tx.toCompact();
|
||||
})
|
||||
};
|
||||
@ -926,6 +931,7 @@ Wallet._fromJSON = function _fromJSON(json, passphrase) {
|
||||
master: bcoin.hd.fromJSON(json.master, passphrase),
|
||||
addressMap: json.addressMap,
|
||||
keys: json.keys,
|
||||
passphrase: passphrase,
|
||||
txs: json.txs.map(function(json) {
|
||||
return bcoin.tx.fromCompact(json);
|
||||
})
|
||||
@ -936,11 +942,20 @@ Wallet.fromJSON = function fromJSON(json, passphrase) {
|
||||
return new Wallet(Wallet._fromJSON(json, passphrase));
|
||||
};
|
||||
|
||||
Wallet.prototype.save = function save(callback) {
|
||||
callback = utils.asyncify(callback);
|
||||
Wallet.prototype._saveAddress = function _saveAddress(address, callback) {
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (!this.options.store && !this.options.db)
|
||||
return callback();
|
||||
if (!this.options.store || !this.options.db)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
return this.db.saveAddress(this.id, address, callback);
|
||||
};
|
||||
|
||||
Wallet.prototype.save = function save(callback) {
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (!this.options.store || !this.options.db)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
return this.db.save(this.id, this, callback);
|
||||
};
|
||||
|
||||
@ -19,20 +19,25 @@ var fs = bcoin.fs;
|
||||
* WalletDB
|
||||
*/
|
||||
|
||||
function WalletDB(options) {
|
||||
function WalletDB(node, options) {
|
||||
if (!(this instanceof WalletDB))
|
||||
return new WalletDB(options);
|
||||
return new WalletDB(node, options);
|
||||
|
||||
if (WalletDB.global)
|
||||
return WalletDB.global;
|
||||
|
||||
if (!(node instanceof bcoin.node)) {
|
||||
options = node;
|
||||
node = null;
|
||||
}
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.node = node;
|
||||
this.options = options;
|
||||
|
||||
this.file = options.file;
|
||||
this.dir = options.dir;
|
||||
this.type = options.type;
|
||||
@ -112,107 +117,128 @@ WalletDB.prototype._init = function _init() {
|
||||
throw new Error('Unknown storage type: ' + this.type);
|
||||
};
|
||||
|
||||
WalletDB.prototype.save = function save(id, json, callback) {
|
||||
callback = utils.asyncify(callback);
|
||||
WalletDB.prototype.getJSON = function getJSON(id, callback) {
|
||||
if (typeof id === 'object')
|
||||
id = id.id;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (this.type === 'leveldb')
|
||||
return this.saveDB(id, json, callback);
|
||||
return this._getDB(id, callback);
|
||||
|
||||
if (this.type === 'file')
|
||||
return this.saveFile(id, json, callback);
|
||||
return this._getFile(id, callback);
|
||||
|
||||
throw new Error('Unknown storage type: ' + this.type);
|
||||
};
|
||||
|
||||
WalletDB.prototype.saveDB = function saveFile(id, json, callback) {
|
||||
var key;
|
||||
WalletDB.prototype.saveJSON = function saveJSON(id, json, callback) {
|
||||
var self = this;
|
||||
|
||||
key = 'w/' + id;
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (json instanceof bcoin.wallet) {
|
||||
json.store = true;
|
||||
json.db = this;
|
||||
json = json.toJSON(this.options.noPool);
|
||||
json = json.toJSON();
|
||||
} else {
|
||||
if (typeof json.v !== 'number') {
|
||||
json = utils.merge({}, json);
|
||||
delete json.store;
|
||||
delete json.db;
|
||||
json = new bcoin.wallet(json).toJSON();
|
||||
}
|
||||
}
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
function cb(err, json) {
|
||||
var batch;
|
||||
|
||||
json = JSON.stringify(json);
|
||||
|
||||
this.db.put(key, json, callback);
|
||||
};
|
||||
|
||||
WalletDB.prototype.saveFile = function saveFile(id, json, callback) {
|
||||
var file, options;
|
||||
|
||||
file = this.dir + '/' + id + '.json';
|
||||
|
||||
if (json instanceof bcoin.wallet) {
|
||||
json.store = true;
|
||||
json.db = this;
|
||||
json = json.toJSON(this.options.noPool);
|
||||
}
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
|
||||
if (!bcoin.fs)
|
||||
return callback();
|
||||
|
||||
json = JSON.stringify(json, null, 2);
|
||||
|
||||
options = {
|
||||
encoding: 'utf8',
|
||||
mode: 0600
|
||||
};
|
||||
|
||||
fs.writeFile(file, json, options, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, file);
|
||||
});
|
||||
};
|
||||
if (json && self.type === 'leveldb') {
|
||||
batch = self.db.batch();
|
||||
Object.keys(json.addressMap).forEach(function(address) {
|
||||
batch.put('a/' + address + '/' + json.id, '');
|
||||
});
|
||||
return batch.write(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, json);
|
||||
});
|
||||
}
|
||||
|
||||
WalletDB.prototype.getJSON = function getJSON(id, passphrase, callback) {
|
||||
if (typeof passphrase === 'function') {
|
||||
callback = passphrase;
|
||||
passphrase = null;
|
||||
}
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
|
||||
if (id instanceof bcoin.wallet) {
|
||||
id = wallet.id;
|
||||
json.store = true;
|
||||
json.db = this;
|
||||
return callback(null, json);
|
||||
}
|
||||
|
||||
if (this.type === 'leveldb')
|
||||
return this.getDB(id, passphrase, callback);
|
||||
return this._saveDB(id, json, cb);
|
||||
|
||||
if (this.type === 'file')
|
||||
return this.getFile(id, passphrase, callback);
|
||||
return this._saveFile(id, json, cb);
|
||||
|
||||
throw new Error('Unknown storage type: ' + this.type);
|
||||
};
|
||||
|
||||
WalletDB.prototype.getFile = function getFile(id, passphrase, callback) {
|
||||
WalletDB.prototype.removeJSON = function removeJSON(id, callback) {
|
||||
var self = this;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (typeof id === 'object')
|
||||
id = id.id;
|
||||
|
||||
function cb(err, json) {
|
||||
var batch;
|
||||
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (json && self.type === 'leveldb') {
|
||||
batch = self.db.batch();
|
||||
Object.keys(json.addressMap).forEach(function(address) {
|
||||
batch.del('a/' + address + '/' + json.id);
|
||||
});
|
||||
return batch.write(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, json);
|
||||
});
|
||||
}
|
||||
|
||||
return callback(null, json);
|
||||
}
|
||||
|
||||
if (this.type === 'leveldb')
|
||||
return this._removeDB(id, cb);
|
||||
|
||||
if (this.type === 'file')
|
||||
return this._removeFile(id, cb);
|
||||
|
||||
throw new Error('Unknown storage type: ' + this.type);
|
||||
};
|
||||
|
||||
WalletDB.prototype.createJSON = function createJSON(id, options, callback) {
|
||||
var self = this;
|
||||
callback = utils.ensure(callback);
|
||||
return this.getJSON(id, function(err, json) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!json)
|
||||
return self.saveJSON(options.id, options, callback);
|
||||
|
||||
return callback(null, json);
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype._getFile = function _getFile(id, callback) {
|
||||
var self = this;
|
||||
var file;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
|
||||
if (!bcoin.fs)
|
||||
return callback();
|
||||
|
||||
if (!id)
|
||||
return callback();
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
file = this.dir + '/' + id + '.json';
|
||||
|
||||
fs.readFile(file, 'utf8', function(err, json) {
|
||||
var options;
|
||||
|
||||
if (err && err.code === 'ENOENT')
|
||||
return callback();
|
||||
|
||||
@ -220,29 +246,24 @@ WalletDB.prototype.getFile = function getFile(id, passphrase, callback) {
|
||||
return callback(err);
|
||||
|
||||
try {
|
||||
options = bcoin.wallet._fromJSON(JSON.parse(json), passphrase);
|
||||
json = JSON.parse(json);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
options.store = true;
|
||||
options.db = self;
|
||||
|
||||
return callback(null, options);
|
||||
return callback(null, json);
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype.getDB = function getDB(id, passphrase, callback) {
|
||||
WalletDB.prototype._getDB = function _getDB(id, callback) {
|
||||
var self = this;
|
||||
var key;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
key = 'w/' + id;
|
||||
|
||||
this.db.get(key, function(err, json) {
|
||||
var options;
|
||||
|
||||
if (err && err.type === 'NotFoundError')
|
||||
return callback();
|
||||
|
||||
@ -250,45 +271,288 @@ WalletDB.prototype.getDB = function getDB(id, passphrase, callback) {
|
||||
return callback(err);
|
||||
|
||||
try {
|
||||
options = bcoin.wallet._fromJSON(JSON.parse(json), passphrase);
|
||||
json = JSON.parse(json);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
options.store = true;
|
||||
options.db = self;
|
||||
return callback(null, json);
|
||||
});
|
||||
};
|
||||
|
||||
return callback(null, options);
|
||||
WalletDB.prototype._saveDB = function _saveDB(id, json, callback) {
|
||||
var key = 'w/' + id;
|
||||
var data;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
data = JSON.stringify(json);
|
||||
|
||||
this.db.put(key, data, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, json);
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype._saveFile = function _saveFile(id, json, callback) {
|
||||
var file = this.dir + '/' + id + '.json';
|
||||
var options, data;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
data = JSON.stringify(json, null, 2);
|
||||
|
||||
options = {
|
||||
encoding: 'utf8',
|
||||
mode: 0600
|
||||
};
|
||||
|
||||
fs.writeFile(file, data, options, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, json);
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype._removeDB = function _removeDB(id, callback) {
|
||||
var self = this;
|
||||
var key = 'w/' + id;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
this._getDB(id, function(err, json) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.db.del(key, function(err) {
|
||||
if (err && err.type !== 'NotFoundError')
|
||||
return callback(err);
|
||||
|
||||
return callback(null, json);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype._removeFile = function _removeFile(id, callback) {
|
||||
var file = this.dir + '/' + id + '.json';
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
this._getFile(id, function(err, json) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
fs.unlink(file, function(err) {
|
||||
if (err && err.code !== 'ENOENT')
|
||||
return callback(err);
|
||||
|
||||
return callback(null, json);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype.get = function get(id, passphrase, callback) {
|
||||
callback = utils.asyncify(callback);
|
||||
return this.getJSON(id, passphrase, function(err, options) {
|
||||
if (typeof passphrase === 'function') {
|
||||
callback = passphrase;
|
||||
passphrase = null;
|
||||
}
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
return this.getJSON(id, function(err, options) {
|
||||
var wallet;
|
||||
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!options)
|
||||
return callback();
|
||||
|
||||
return callback(null, new bcoin.wallet(options));
|
||||
wallet = bcoin.wallet.fromJSON(options, passphrase);
|
||||
wallet.store = true;
|
||||
wallet.db = self;
|
||||
|
||||
return callback(null, wallet);
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype.save = function save(options, callback) {
|
||||
var self = this;
|
||||
var passphrase = options.passphrase;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
return this.saveJSON(options.id, options, callback);
|
||||
};
|
||||
|
||||
WalletDB.prototype.remove = function save(id, callback) {
|
||||
var self = this;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (id instanceof bcoin.wallet) {
|
||||
id.store = false;
|
||||
id.db = null;
|
||||
id = id.id;
|
||||
}
|
||||
|
||||
return this.removeJSON(id, callback);
|
||||
};
|
||||
|
||||
WalletDB.prototype.create = function create(options, callback) {
|
||||
var self = this;
|
||||
callback = utils.asyncify(callback);
|
||||
return this.getJSON(options.id, options.passphrase, function(err, opt) {
|
||||
var passphrase = options.passphrase;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (options instanceof bcoin.wallet) {
|
||||
options.store = true;
|
||||
options.db = this;
|
||||
}
|
||||
|
||||
return this.createJSON(options.id, options, function(err, json) {
|
||||
var wallet;
|
||||
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!opt) {
|
||||
options.store = true;
|
||||
options.db = self;
|
||||
return callback(null, new bcoin.wallet(options));
|
||||
}
|
||||
wallet = bcoin.wallet.fromJSON(json, options.passphrase);
|
||||
wallet.store = true;
|
||||
wallet.db = self;
|
||||
|
||||
return callback(null, new bcoin.wallet(opt));
|
||||
return callback(null, wallet);
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype.saveAddress = function saveAddress(id, address, callback) {
|
||||
callback = utils.ensure(callback);
|
||||
if (this.type !== 'leveldb')
|
||||
return utils.nextTick(callback);
|
||||
this.db.put('a/' + address + '/' + id, '', callback);
|
||||
};
|
||||
|
||||
WalletDB.prototype.removeAddress = function removeAddress(id, address, callback) {
|
||||
callback = utils.ensure(callback);
|
||||
if (this.type !== 'leveldb')
|
||||
return utils.nextTick(callback);
|
||||
this.db.del('a/' + address + '/' + id, callback);
|
||||
};
|
||||
|
||||
WalletDB.prototype._getIDs = function _getIDs(address, callback) {
|
||||
var self = this;
|
||||
var ids = [];
|
||||
|
||||
var iter = this.db.db.iterator({
|
||||
gte: 'a/' + address,
|
||||
lte: 'a/' + address + '~',
|
||||
keys: true,
|
||||
values: false,
|
||||
fillCache: false,
|
||||
keyAsBuffer: false
|
||||
});
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
(function next() {
|
||||
iter.next(function(err, key, value) {
|
||||
if (err) {
|
||||
return iter.end(function() {
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
|
||||
if (key === undefined) {
|
||||
return iter.end(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, ids);
|
||||
});
|
||||
}
|
||||
|
||||
ids.push(key.split('/')[2]);
|
||||
|
||||
next();
|
||||
});
|
||||
})();
|
||||
};
|
||||
|
||||
WalletDB.prototype.test = function test(addresses, callback) {
|
||||
var self = this;
|
||||
|
||||
if (this.type !== 'leveldb')
|
||||
return utils.nextTick(callback);
|
||||
|
||||
utils.forEachSerial(addresses, function(address, next) {
|
||||
self._getIDs(address, function(err, ids) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (ids.length > 0)
|
||||
return callback(null, ids);
|
||||
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback();
|
||||
});
|
||||
};
|
||||
|
||||
WalletDB.prototype.ownInput = function ownInput(tx, callback) {
|
||||
var self = this;
|
||||
var addresses;
|
||||
|
||||
if (tx.getAddress) {
|
||||
assert(tx instanceof bcoin.input);
|
||||
addresses = tx.getAddress();
|
||||
if (addresses)
|
||||
addresses = [addresses];
|
||||
else
|
||||
addresses = [];
|
||||
} else {
|
||||
addresses = tx.getInputAddresses();
|
||||
}
|
||||
|
||||
return this.test(addresses, callback);
|
||||
};
|
||||
|
||||
WalletDB.prototype.ownOutput = function ownOutput(tx, callback) {
|
||||
var self = this;
|
||||
var addresses;
|
||||
|
||||
if (tx.getAddress) {
|
||||
assert(tx instanceof bcoin.output);
|
||||
addresses = tx.getAddress();
|
||||
if (addresses)
|
||||
addresses = [addresses];
|
||||
else
|
||||
addresses = [];
|
||||
} else {
|
||||
addresses = tx.getOutputAddresses();
|
||||
}
|
||||
|
||||
return this.test(addresses, callback);
|
||||
};
|
||||
|
||||
WalletDB.prototype.ownTX = function ownTX(tx, callback) {
|
||||
var self = this;
|
||||
return this.ownInput(tx, function(err, input) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return self.ownOutput(tx, function(err, output) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (input || output)
|
||||
return callback(null, input || [], output || []);
|
||||
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -296,4 +560,6 @@ WalletDB.prototype.create = function create(options, callback) {
|
||||
* Expose
|
||||
*/
|
||||
|
||||
var self = this;
|
||||
var self = this;
|
||||
module.exports = WalletDB;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user