refactor. allow tx querying by timestamp.
This commit is contained in:
parent
e962686e93
commit
f67902a9cf
@ -68,11 +68,7 @@ Address.prototype.getID = function getID() {
|
|||||||
Address.prototype.addKey = function addKey(key) {
|
Address.prototype.addKey = function addKey(key) {
|
||||||
key = utils.ensureBuffer(key);
|
key = utils.ensureBuffer(key);
|
||||||
|
|
||||||
var has = this.keys.some(function(k) {
|
if (utils.indexOf(this.keys, key) !== -1)
|
||||||
return utils.isEqual(k, key);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (has)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.keys.push(key);
|
this.keys.push(key);
|
||||||
@ -81,15 +77,13 @@ Address.prototype.addKey = function addKey(key) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.removeKey = function removeKey(key) {
|
Address.prototype.removeKey = function removeKey(key) {
|
||||||
|
var index;
|
||||||
|
|
||||||
key = utils.ensureBuffer(key);
|
key = utils.ensureBuffer(key);
|
||||||
|
|
||||||
var index = this.keys.map(function(k, i) {
|
index = utils.indexOf(this.keys, key);
|
||||||
return utils.isEqual(k, key) ? i : null;
|
|
||||||
}).filter(function(i) {
|
|
||||||
return i !== null;
|
|
||||||
})[0];
|
|
||||||
|
|
||||||
if (index == null)
|
if (index === -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.keys.splice(index, 1);
|
this.keys.splice(index, 1);
|
||||||
@ -175,7 +169,8 @@ Address.prototype.getProgramAddress = function getProgramAddress() {
|
|||||||
if (this._programAddress)
|
if (this._programAddress)
|
||||||
return this._programAddress;
|
return this._programAddress;
|
||||||
|
|
||||||
this._programAddress = Address.compileHash(this.getProgramHash(), 'scripthash');
|
this._programAddress =
|
||||||
|
Address.compileHash(this.getProgramHash(), 'scripthash');
|
||||||
|
|
||||||
return this._programAddress;
|
return this._programAddress;
|
||||||
};
|
};
|
||||||
@ -215,10 +210,13 @@ Address.prototype.getScriptAddress = function getScriptAddress() {
|
|||||||
if (this._scriptAddress)
|
if (this._scriptAddress)
|
||||||
return this._scriptAddress;
|
return this._scriptAddress;
|
||||||
|
|
||||||
if (this.witness)
|
if (this.witness) {
|
||||||
this._scriptAddress = Address.compileHash(this.getScriptHash256(), 'witnessscripthash');
|
this._scriptAddress =
|
||||||
else
|
Address.compileHash(this.getScriptHash256(), 'witnessscripthash');
|
||||||
this._scriptAddress = Address.compileHash(this.getScriptHash160(), 'scripthash');
|
} else {
|
||||||
|
this._scriptAddress =
|
||||||
|
Address.compileHash(this.getScriptHash160(), 'scripthash');
|
||||||
|
}
|
||||||
|
|
||||||
return this._scriptAddress;
|
return this._scriptAddress;
|
||||||
};
|
};
|
||||||
@ -273,57 +271,26 @@ Address.prototype._getAddressMap = function _getAddressMap() {
|
|||||||
return this.addressMap;
|
return this.addressMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.ownOutput = function ownOutput(tx, index) {
|
|
||||||
var addressMap = this._getAddressMap();
|
|
||||||
var outputs = tx.outputs;
|
|
||||||
|
|
||||||
if ((tx instanceof bcoin.output) || (tx instanceof bcoin.coin)) {
|
|
||||||
outputs = [tx];
|
|
||||||
tx = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
outputs = outputs.filter(function(output, i) {
|
|
||||||
if (index != null && index !== i)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return output.test(addressMap);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
if (outputs.length === 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return outputs;
|
|
||||||
};
|
|
||||||
|
|
||||||
Address.prototype.ownInput = function ownInput(tx, index) {
|
Address.prototype.ownInput = function ownInput(tx, index) {
|
||||||
var addressMap = this._getAddressMap();
|
var addressMap = this._getAddressMap();
|
||||||
var inputs = tx.inputs;
|
|
||||||
|
|
||||||
if (tx instanceof bcoin.input) {
|
if (tx instanceof bcoin.input)
|
||||||
inputs = [tx];
|
return tx.test(addressMap);
|
||||||
tx = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputs = inputs.filter(function(input, i) {
|
return tx.testInputs(addressMap, index);
|
||||||
if (index != null && index !== i)
|
};
|
||||||
return false;
|
|
||||||
|
|
||||||
if (input.output)
|
Address.prototype.ownOutput = function ownOutput(tx, index) {
|
||||||
return input.output.test(addressMap);
|
var addressMap = this._getAddressMap();
|
||||||
|
|
||||||
return input.test(addressMap);
|
if (tx instanceof bcoin.output)
|
||||||
}, this);
|
return tx.test(addressMap);
|
||||||
|
|
||||||
if (inputs.length === 0)
|
return tx.testOutputs(addressMap, index);
|
||||||
return false;
|
|
||||||
|
|
||||||
return inputs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.scriptInputs = function scriptInputs(tx, index) {
|
Address.prototype.scriptInputs = function scriptInputs(tx, index) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var publicKey = this.getPublicKey();
|
|
||||||
var redeem = this.getScript();
|
|
||||||
|
|
||||||
if (index && typeof index === 'object')
|
if (index && typeof index === 'object')
|
||||||
index = tx.inputs.indexOf(index);
|
index = tx.inputs.indexOf(index);
|
||||||
@ -347,13 +314,11 @@ Address.prototype.scriptInputs = function scriptInputs(tx, index) {
|
|||||||
|
|
||||||
Address.prototype.signInputs = function signInputs(tx, type, index) {
|
Address.prototype.signInputs = function signInputs(tx, type, index) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var key = this.key;
|
|
||||||
var total = 0;
|
|
||||||
|
|
||||||
if (index && typeof index === 'object')
|
if (index && typeof index === 'object')
|
||||||
index = tx.inputs.indexOf(index);
|
index = tx.inputs.indexOf(index);
|
||||||
|
|
||||||
if (!key.privateKey)
|
if (!this.key.privateKey)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return tx.inputs.reduce(function(total, input, i) {
|
return tx.inputs.reduce(function(total, input, i) {
|
||||||
@ -375,13 +340,11 @@ Address.prototype.signInputs = function signInputs(tx, type, index) {
|
|||||||
|
|
||||||
Address.prototype.sign = function sign(tx, type, index) {
|
Address.prototype.sign = function sign(tx, type, index) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var redeem = this.getScript();
|
|
||||||
var key = this.key;
|
|
||||||
|
|
||||||
if (index && typeof index === 'object')
|
if (index && typeof index === 'object')
|
||||||
index = tx.inputs.indexOf(index);
|
index = tx.inputs.indexOf(index);
|
||||||
|
|
||||||
if (!key.privateKey)
|
if (!this.key.privateKey)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Add signature script to each input
|
// Add signature script to each input
|
||||||
|
|||||||
@ -201,9 +201,9 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
// Update wallet / sync address depth
|
// Update wallet / sync address depth
|
||||||
this.put('/wallet/:id', function(req, res, next, send) {
|
this.put('/wallet/:id', function(req, res, next, send) {
|
||||||
var id = req.params.id;
|
var id = req.params.id;
|
||||||
var receive = req.body.receiveDepth;
|
var receive = req.body.receiveDepth >>> 0;
|
||||||
var change = req.body.changeDepth;
|
var change = req.body.changeDepth >>> 0;
|
||||||
self.node.walletdb.syncDepth(id, receive, change, function(err) {
|
self.node.walletdb.setDepth(id, receive, change, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
|
|||||||
@ -117,6 +117,10 @@ MerkleBlock.prototype._verify = function _verify() {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MerkleBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
MerkleBlock.prototype.inspect = function inspect() {
|
MerkleBlock.prototype.inspect = function inspect() {
|
||||||
var copy = bcoin.merkleblock(this);
|
var copy = bcoin.merkleblock(this);
|
||||||
copy.__proto__ = null;
|
copy.__proto__ = null;
|
||||||
|
|||||||
@ -1282,7 +1282,7 @@ Pool.prototype.searchWallet = function(wallet, callback) {
|
|||||||
if (!this.options.spv)
|
if (!this.options.spv)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
wallet.getLast(function(err, ts, height) {
|
wallet.getLastTime(function(err, ts, height) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
|
|||||||
@ -76,7 +76,9 @@ TXPool.prototype._lock = function _lock(func, args, force) {
|
|||||||
|
|
||||||
TXPool.prototype.getMap = function getMap(tx, callback) {
|
TXPool.prototype.getMap = function getMap(tx, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var addresses = tx.getAddresses();
|
var input = tx.getInputAddresses();
|
||||||
|
var output = tx.getOutputAddresses();
|
||||||
|
var addresses = utils.uniqs(input.concat(output));
|
||||||
var map;
|
var map;
|
||||||
|
|
||||||
function cb(err, map) {
|
function cb(err, map) {
|
||||||
@ -87,12 +89,12 @@ TXPool.prototype.getMap = function getMap(tx, callback) {
|
|||||||
map.output = [];
|
map.output = [];
|
||||||
map.all = [];
|
map.all = [];
|
||||||
|
|
||||||
tx.getInputAddresses().forEach(function(address) {
|
input.forEach(function(address) {
|
||||||
assert(map[address]);
|
assert(map[address]);
|
||||||
map.input = map.input.concat(map[address]);
|
map.input = map.input.concat(map[address]);
|
||||||
});
|
});
|
||||||
|
|
||||||
tx.getOutputAddresses().forEach(function(address) {
|
output.forEach(function(address) {
|
||||||
assert(map[address]);
|
assert(map[address]);
|
||||||
map.output = map.output.concat(map[address]);
|
map.output = map.output.concat(map[address]);
|
||||||
});
|
});
|
||||||
@ -122,7 +124,6 @@ TXPool.prototype.mapAddresses = function mapAddresses(address, callback) {
|
|||||||
var iter;
|
var iter;
|
||||||
|
|
||||||
if (Array.isArray(address)) {
|
if (Array.isArray(address)) {
|
||||||
address = utils.uniqs(address);
|
|
||||||
return utils.forEachSerial(address, function(address, next) {
|
return utils.forEachSerial(address, function(address, next) {
|
||||||
self.mapAddresses(address, function(err, res) {
|
self.mapAddresses(address, function(err, res) {
|
||||||
if (err)
|
if (err)
|
||||||
@ -166,7 +167,6 @@ TXPool.prototype.mapAddresses = function mapAddresses(address, callback) {
|
|||||||
return iter.end(function(err) {
|
return iter.end(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
map[address] = utils.uniqs(map[address]);
|
|
||||||
return callback(null, map);
|
return callback(null, map);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -261,6 +261,13 @@ TXPool.prototype.add = function add(tx, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function pad32(num) {
|
||||||
|
num = num + '';
|
||||||
|
while (num.length < 10)
|
||||||
|
num = '0' + num;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
// This big scary function is what a persistent tx pool
|
// This big scary function is what a persistent tx pool
|
||||||
// looks like. It's a semi mempool in that it can handle
|
// looks like. It's a semi mempool in that it can handle
|
||||||
// receiving txs out of order.
|
// receiving txs out of order.
|
||||||
@ -269,10 +276,10 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
var prefix = this.prefix + '/';
|
var prefix = this.prefix + '/';
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var updated = false;
|
var updated = false;
|
||||||
var own = false;
|
|
||||||
var uniq = {};
|
|
||||||
var batch;
|
var batch;
|
||||||
|
|
||||||
|
assert(tx.ts > 0 || tx.ps > 0);
|
||||||
|
|
||||||
var unlock = this._lock(add, [tx, map, callback], force);
|
var unlock = this._lock(add, [tx, map, callback], force);
|
||||||
if (!unlock)
|
if (!unlock)
|
||||||
return;
|
return;
|
||||||
@ -290,38 +297,29 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
batch = self.db.batch();
|
batch = self.db.batch();
|
||||||
|
|
||||||
if (existing) {
|
if (existing) {
|
||||||
own = true;
|
|
||||||
// Tricky - update the tx and coin in storage,
|
// Tricky - update the tx and coin in storage,
|
||||||
// and remove pending flag to mark as confirmed.
|
// and remove pending flag to mark as confirmed.
|
||||||
if (existing.ts === 0 && tx.ts !== 0) {
|
if (existing.ts === 0 && tx.ts !== 0) {
|
||||||
|
assert(tx.height >= 0);
|
||||||
|
assert(existing.ps > 0);
|
||||||
|
|
||||||
batch.put(prefix + 't/t/' + hash, tx.toExtended());
|
batch.put(prefix + 't/t/' + hash, tx.toExtended());
|
||||||
batch.put(prefix + 't/h/' + tx.height + '/' + hash, DUMMY);
|
batch.put(prefix + 't/h/h/' + pad32(tx.height) + '/' + hash, DUMMY);
|
||||||
batch.del(prefix + 'p/t/' + hash);
|
batch.del(prefix + 't/s/s/' + pad32(existing.ps) + '/' + hash);
|
||||||
|
batch.put(prefix + 't/s/s/' + pad32(tx.ts) + '/' + hash, DUMMY);
|
||||||
|
batch.del(prefix + 't/p/t/' + hash);
|
||||||
|
|
||||||
tx.inputs.forEach(function(input) {
|
map.all.forEach(function(id) {
|
||||||
var address = input.getAddress();
|
batch.put(
|
||||||
|
prefix + 't/h/a/' + id + '/' + pad32(tx.height) + '/' + hash, DUMMY);
|
||||||
if (input.isCoinbase())
|
batch.del(
|
||||||
return;
|
prefix + 't/s/a/' + id + '/' + pad32(existing.ps) + '/' + hash);
|
||||||
|
batch.put(
|
||||||
if (address && !uniq[address]) {
|
prefix + 't/s/a/' + id + '/' + pad32(tx.ts) + '/' + hash, DUMMY);
|
||||||
uniq[address] = true;
|
batch.del(prefix + 't/p/a/' + id + '/' + hash);
|
||||||
map[address].forEach(function(id) {
|
|
||||||
batch.del(prefix + 'p/a/' + id + '/' + hash);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
utils.forEachSerial(tx.outputs, function(output, next, i) {
|
utils.forEachSerial(tx.outputs, function(output, next, i) {
|
||||||
var address = output.getAddress();
|
|
||||||
|
|
||||||
if (address && !uniq[address]) {
|
|
||||||
uniq[address] = true;
|
|
||||||
map[address].forEach(function(id) {
|
|
||||||
batch.del(prefix + 'p/a/' + id + '/' + hash);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
self.getCoin(hash, i, function(err, coin) {
|
self.getCoin(hash, i, function(err, coin) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
@ -355,6 +353,31 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
return done(null, false);
|
return done(null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batch.put(prefix + 't/t/' + hash, tx.toExtended());
|
||||||
|
|
||||||
|
if (tx.ts === 0) {
|
||||||
|
assert(tx.ps > 0);
|
||||||
|
batch.put(prefix + 't/p/t/' + hash, DUMMY);
|
||||||
|
batch.put(prefix + 't/s/s/' + pad32(tx.ps) + '/' + hash, DUMMY);
|
||||||
|
} else {
|
||||||
|
batch.put(prefix + 't/h/h/' + pad32(tx.height) + '/' + hash, DUMMY);
|
||||||
|
batch.put(prefix + 't/s/s/' + pad32(tx.ts) + '/' + hash, DUMMY);
|
||||||
|
}
|
||||||
|
|
||||||
|
map.all.forEach(function(id) {
|
||||||
|
batch.put(prefix + 't/a/' + id + '/' + hash, DUMMY);
|
||||||
|
if (tx.ts === 0) {
|
||||||
|
batch.put(prefix + 't/p/a/' + id + '/' + hash, DUMMY);
|
||||||
|
batch.put(
|
||||||
|
prefix + 't/s/a/' + id + '/' + pad32(tx.ps) + '/' + hash, DUMMY);
|
||||||
|
} else {
|
||||||
|
batch.put(
|
||||||
|
prefix + 't/h/a/' + id + '/' + pad32(tx.height) + '/' + hash, DUMMY);
|
||||||
|
batch.put(
|
||||||
|
prefix + 't/s/a/' + id + '/' + pad32(tx.ts) + '/' + hash, DUMMY);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Consume unspent money or add orphans
|
// Consume unspent money or add orphans
|
||||||
utils.forEachSerial(tx.inputs, function(input, next, i) {
|
utils.forEachSerial(tx.inputs, function(input, next, i) {
|
||||||
var key;
|
var key;
|
||||||
@ -372,15 +395,6 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
|
|
||||||
address = input.getAddress();
|
address = input.getAddress();
|
||||||
|
|
||||||
if (address && !uniq[address]) {
|
|
||||||
uniq[address] = true;
|
|
||||||
map[address].forEach(function(id) {
|
|
||||||
batch.put(prefix + 't/a/' + id + '/' + hash, DUMMY);
|
|
||||||
if (tx.ts === 0)
|
|
||||||
batch.put(prefix + 'p/a/' + id + '/' + hash, DUMMY);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (coin) {
|
if (coin) {
|
||||||
// Add TX to inputs and spend money
|
// Add TX to inputs and spend money
|
||||||
input.output = coin;
|
input.output = coin;
|
||||||
@ -393,7 +407,6 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
return done(null, false);
|
return done(null, false);
|
||||||
|
|
||||||
updated = true;
|
updated = true;
|
||||||
own = true;
|
|
||||||
|
|
||||||
if (address) {
|
if (address) {
|
||||||
map[address].forEach(function(id) {
|
map[address].forEach(function(id) {
|
||||||
@ -416,8 +429,6 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
if (!address || !map[address].length)
|
if (!address || !map[address].length)
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
own = true;
|
|
||||||
|
|
||||||
self.getTX(input.prevout.hash, function(err, result) {
|
self.getTX(input.prevout.hash, function(err, result) {
|
||||||
if (err)
|
if (err)
|
||||||
return done(err);
|
return done(err);
|
||||||
@ -452,7 +463,6 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
|
|
||||||
key = hash + '/' + i;
|
key = hash + '/' + i;
|
||||||
coin = bcoin.coin(tx, i);
|
coin = bcoin.coin(tx, i);
|
||||||
own = true;
|
|
||||||
|
|
||||||
self._getOrphans(key, function(err, orphans) {
|
self._getOrphans(key, function(err, orphans) {
|
||||||
var some = false;
|
var some = false;
|
||||||
@ -504,15 +514,6 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
if (!orphans) {
|
if (!orphans) {
|
||||||
if (address && !uniq[address]) {
|
|
||||||
uniq[address] = true;
|
|
||||||
map[address].forEach(function(id) {
|
|
||||||
batch.put(prefix + 't/a/' + id + '/' + hash, DUMMY);
|
|
||||||
if (tx.ts === 0)
|
|
||||||
batch.put(prefix + 'p/a/' + id + '/' + hash, DUMMY);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (address) {
|
if (address) {
|
||||||
map[address].forEach(function(id) {
|
map[address].forEach(function(id) {
|
||||||
batch.put(
|
batch.put(
|
||||||
@ -533,15 +534,6 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
|
|||||||
if (err)
|
if (err)
|
||||||
return done(err);
|
return done(err);
|
||||||
|
|
||||||
if (!own)
|
|
||||||
return done(null, false);
|
|
||||||
|
|
||||||
batch.put(prefix + 't/t/' + hash, tx.toExtended());
|
|
||||||
if (tx.ts === 0)
|
|
||||||
batch.put(prefix + 'p/t/' + hash, DUMMY);
|
|
||||||
else
|
|
||||||
batch.put(prefix + 't/h/' + tx.height + '/' + hash, DUMMY);
|
|
||||||
|
|
||||||
batch.write(function(err) {
|
batch.write(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return done(err);
|
return done(err);
|
||||||
@ -620,13 +612,27 @@ TXPool.prototype._remove = function remove(tx, map, callback) {
|
|||||||
var prefix = this.prefix + '/';
|
var prefix = this.prefix + '/';
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var batch = this.db.batch();
|
var batch = this.db.batch();
|
||||||
var uniq = {};
|
|
||||||
|
|
||||||
batch.del(prefix + 't/t/' + hash);
|
batch.del(prefix + 't/t/' + hash);
|
||||||
if (tx.ts === 0)
|
|
||||||
batch.del(prefix + 'p/t/' + hash);
|
if (tx.ts === 0) {
|
||||||
else
|
batch.del(prefix + 't/p/t/' + hash);
|
||||||
batch.del(prefix + 't/h/' + tx.height + '/' + hash);
|
batch.del(prefix + 't/s/s/' + pad32(tx.ps) + '/' + hash);
|
||||||
|
} else {
|
||||||
|
batch.del(prefix + 't/h/h/' + pad32(tx.height) + '/' + hash);
|
||||||
|
batch.del(prefix + 't/s/s/' + pad32(tx.ts) + '/' + hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
map.all.forEach(function(id) {
|
||||||
|
batch.del(prefix + 't/a/' + id + '/' + hash);
|
||||||
|
if (tx.ts === 0) {
|
||||||
|
batch.del(prefix + 't/p/a/' + id + '/' + hash);
|
||||||
|
batch.del(prefix + 't/s/a/' + id + '/' + pad32(tx.ps) + '/' + hash);
|
||||||
|
} else {
|
||||||
|
batch.del(prefix + 't/h/a/' + id + '/' + pad32(tx.height) + '/' + hash);
|
||||||
|
batch.del(prefix + 't/s/a/' + id + '/' + pad32(tx.ts) + '/' + hash);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.fillTX(tx, function(err) {
|
this.fillTX(tx, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
@ -638,15 +644,6 @@ TXPool.prototype._remove = function remove(tx, map, callback) {
|
|||||||
if (input.isCoinbase())
|
if (input.isCoinbase())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (address && !uniq[address]) {
|
|
||||||
uniq[address] = true;
|
|
||||||
map[address].forEach(function(id) {
|
|
||||||
batch.del(prefix + 't/a/' + id + '/' + hash);
|
|
||||||
if (tx.ts === 0)
|
|
||||||
batch.del(prefix + 'p/a/' + id + '/' + hash);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!input.output)
|
if (!input.output)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -670,15 +667,6 @@ TXPool.prototype._remove = function remove(tx, map, callback) {
|
|||||||
tx.outputs.forEach(function(output, i) {
|
tx.outputs.forEach(function(output, i) {
|
||||||
var address = output.getAddress();
|
var address = output.getAddress();
|
||||||
|
|
||||||
if (address && !uniq[address]) {
|
|
||||||
uniq[address] = true;
|
|
||||||
map[address].forEach(function(id) {
|
|
||||||
batch.del(prefix + 't/a/' + id + '/' + hash);
|
|
||||||
if (tx.ts === 0)
|
|
||||||
batch.del(prefix + 'p/a/' + id + '/' + hash);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (address) {
|
if (address) {
|
||||||
map[address].forEach(function(id) {
|
map[address].forEach(function(id) {
|
||||||
batch.del(prefix + 'u/a/' + id + '/' + hash + '/' + i);
|
batch.del(prefix + 'u/a/' + id + '/' + hash + '/' + i);
|
||||||
@ -735,10 +723,13 @@ TXPool.prototype.unconfirm = function unconfirm(hash, callback) {
|
|||||||
TXPool.prototype._unconfirm = function unconfirm(tx, map, callback) {
|
TXPool.prototype._unconfirm = function unconfirm(tx, map, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var prefix = this.prefix + '/';
|
var prefix = this.prefix + '/';
|
||||||
var uniq = {};
|
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var batch = this.db.batch();
|
var batch = this.db.batch();
|
||||||
var height = tx.height;
|
var height = tx.height;
|
||||||
|
var ts = tx.ts;
|
||||||
|
|
||||||
|
if (height !== -1)
|
||||||
|
return callback(null, false);
|
||||||
|
|
||||||
tx.height = -1;
|
tx.height = -1;
|
||||||
tx.ps = utils.now();
|
tx.ps = utils.now();
|
||||||
@ -747,35 +738,19 @@ TXPool.prototype._unconfirm = function unconfirm(tx, map, callback) {
|
|||||||
tx.block = null;
|
tx.block = null;
|
||||||
|
|
||||||
batch.put(prefix + 't/t/' + hash, tx.toExtended());
|
batch.put(prefix + 't/t/' + hash, tx.toExtended());
|
||||||
batch.put(prefix + 'p/t/' + hash, DUMMY);
|
batch.put(prefix + 't/p/t/' + hash, DUMMY);
|
||||||
batch.del(prefix + 't/h/' + height + '/' + hash);
|
batch.del(prefix + 't/h/h/' + pad32(height) + '/' + hash);
|
||||||
|
batch.del(prefix + 't/s/s/' + pad32(ts) + '/' + hash);
|
||||||
|
batch.put(prefix + 't/s/s/' + pad32(tx.ps) + '/' + hash, DUMMY);
|
||||||
|
|
||||||
tx.inputs.forEach(function(input) {
|
map.all.forEach(function(id) {
|
||||||
var address;
|
batch.del(prefix + 't/h/a/' + id + '/' + pad32(height) + '/' + hash);
|
||||||
|
batch.del(prefix + 't/s/a/' + id + '/' + pad32(ts) + '/' + hash);
|
||||||
if (input.isCoinbase())
|
batch.put(prefix + 't/s/a/' + id + '/' + pad32(tx.ps) + '/' + hash, DUMMY);
|
||||||
return;
|
batch.put(prefix + 't/p/a/' + id + '/' + hash, DUMMY);
|
||||||
|
|
||||||
address = input.getAddress();
|
|
||||||
|
|
||||||
if (address && !uniq[address]) {
|
|
||||||
uniq[address] = true;
|
|
||||||
map[address].forEach(function(id) {
|
|
||||||
batch.put(prefix + 'p/a/' + id + '/' + hash, DUMMY);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
utils.forEachSerial(tx.outputs, function(output, next, i) {
|
utils.forEachSerial(tx.outputs, function(output, next, i) {
|
||||||
var address = output.getAddress();
|
|
||||||
|
|
||||||
if (address && !uniq[address]) {
|
|
||||||
uniq[address] = true;
|
|
||||||
map[address].forEach(function(id) {
|
|
||||||
batch.put(prefix + 'p/a/' + id + '/' + hash, DUMMY);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
self.getCoin(hash, i, function(err, coin) {
|
self.getCoin(hash, i, function(err, coin) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
@ -897,8 +872,8 @@ TXPool.prototype.getPendingHashes = function getPendingHashes(address, callback)
|
|||||||
}
|
}
|
||||||
|
|
||||||
iter = this.db.db.iterator({
|
iter = this.db.db.iterator({
|
||||||
gte: address ? prefix + 'p/a/' + address : prefix + 'p/t',
|
gte: address ? prefix + 't/p/a/' + address : prefix + 't/p/t',
|
||||||
lte: address ? prefix + 'p/a/' + address + '~' : prefix + 'p/t~',
|
lte: address ? prefix + 't/p/a/' + address + '~' : prefix + 't/p/t~',
|
||||||
keys: true,
|
keys: true,
|
||||||
values: false,
|
values: false,
|
||||||
fillCache: false,
|
fillCache: false,
|
||||||
@ -994,41 +969,27 @@ TXPool.prototype.getCoinIDs = function getCoinIDs(address, callback) {
|
|||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
|
|
||||||
TXPool.prototype.getHeightHashes = function getHeightHashes(height, callback) {
|
TXPool.prototype.getHeightRangeHashes = function getHeightRangeHashes(address, options, callback) {
|
||||||
var prefix = this.prefix + '/';
|
var prefix = this.prefix + '/';
|
||||||
var self = this;
|
var self = this;
|
||||||
var txs = [];
|
var txs = [];
|
||||||
|
var total = 0;
|
||||||
var iter;
|
var iter;
|
||||||
|
|
||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
if (Array.isArray(height)) {
|
|
||||||
return utils.forEachSerial(height, function(height, next) {
|
|
||||||
self.getHeightHashes(height, function(err, tx) {
|
|
||||||
if (err)
|
|
||||||
return next(err);
|
|
||||||
|
|
||||||
txs = txs.concat(tx);
|
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
}, function(err) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
txs = utils.uniqs(txs);
|
|
||||||
|
|
||||||
return callback(null, txs);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
iter = this.db.db.iterator({
|
iter = this.db.db.iterator({
|
||||||
gte: prefix + 't/h/' + height,
|
gte: address
|
||||||
lte: prefix + 't/h/' + height + '~',
|
? prefix + 't/h/a/' + address + '/' + pad32(options.start) + '/'
|
||||||
|
: prefix + 't/h/h/' + pad32(options.start) + '/',
|
||||||
|
lte: address
|
||||||
|
? prefix + 't/h/a/' + address + '/' + pad32(options.end) + '/~'
|
||||||
|
: prefix + 't/h/h/' + pad32(options.end) + '/~',
|
||||||
keys: true,
|
keys: true,
|
||||||
values: false,
|
values: false,
|
||||||
fillCache: false,
|
fillCache: false,
|
||||||
keyAsBuffer: false
|
keyAsBuffer: false,
|
||||||
|
reverse: options.reverse
|
||||||
});
|
});
|
||||||
|
|
||||||
(function next() {
|
(function next() {
|
||||||
@ -1049,11 +1010,105 @@ TXPool.prototype.getHeightHashes = function getHeightHashes(height, callback) {
|
|||||||
|
|
||||||
txs.push(key.split('/')[4]);
|
txs.push(key.split('/')[4]);
|
||||||
|
|
||||||
|
if (++total === options.limit)
|
||||||
|
return callback(null, txs);
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TXPool.prototype.getHeightHashes = function getHeightHashes(height, callback) {
|
||||||
|
return this.getHeightRangeHashes({ start: height, end: height }, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
TXPool.prototype.getTimeRangeHashes = function getTimeRangeHashes(address, options, callback) {
|
||||||
|
var prefix = this.prefix + '/';
|
||||||
|
var self = this;
|
||||||
|
var txs = [];
|
||||||
|
var total = 0;
|
||||||
|
var iter;
|
||||||
|
|
||||||
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
|
iter = this.db.db.iterator({
|
||||||
|
gte: address
|
||||||
|
? prefix + 't/s/a/' + address + '/' + pad32(options.start) + '/'
|
||||||
|
: prefix + 't/s/s/' + pad32(options.start) + '/',
|
||||||
|
lte: address
|
||||||
|
? prefix + 't/s/a/' + address + '/' + pad32(options.end) + '/~'
|
||||||
|
: prefix + 't/s/s/' + pad32(options.end) + '/~',
|
||||||
|
keys: true,
|
||||||
|
values: false,
|
||||||
|
fillCache: false,
|
||||||
|
keyAsBuffer: false,
|
||||||
|
reverse: options.reverse
|
||||||
|
});
|
||||||
|
|
||||||
|
(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, txs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
txs.push(key.split('/')[4]);
|
||||||
|
|
||||||
|
if (++total === options.limit)
|
||||||
|
return callback(null, txs);
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
|
TXPool.prototype.getTimeRange = function getLast(address, options, callback) {
|
||||||
|
var self = this;
|
||||||
|
var txs = [];
|
||||||
|
|
||||||
|
return this.getTimeRangeHashes(address, options, function(err, hashes) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
utils.forEachSerial(hashes, function(hash, next) {
|
||||||
|
self.getTX(hash, function(err, tx) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
if (!tx)
|
||||||
|
return next();
|
||||||
|
|
||||||
|
txs.push(tx);
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, function(err) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
return callback(null, txs);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
TXPool.prototype.getLast = function getLast(address, limit, callback) {
|
||||||
|
return this.getTimeRange(address, {
|
||||||
|
start: 0,
|
||||||
|
end: 0xffffffff,
|
||||||
|
reverse: true,
|
||||||
|
limit: limit
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
TXPool.prototype.getAllByAddress = function getAllByAddress(address, callback) {
|
TXPool.prototype.getAllByAddress = function getAllByAddress(address, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var txs = [];
|
var txs = [];
|
||||||
@ -1083,7 +1138,7 @@ TXPool.prototype.getAllByAddress = function getAllByAddress(address, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
TXPool.prototype.getLast = function getLast(address, callback) {
|
TXPool.prototype.getLastTime = function getLastTime(address, callback) {
|
||||||
return this.getAllByAddress(address, function(err, txs) {
|
return this.getAllByAddress(address, function(err, txs) {
|
||||||
var lastTs, lastHeight;
|
var lastTs, lastHeight;
|
||||||
|
|
||||||
|
|||||||
@ -152,12 +152,14 @@ Wallet.prototype._init = function _init() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.provider.on('unconfirmed', function(tx) {
|
this.provider.on('unconfirmed', function(tx) {
|
||||||
self.syncOutputDepth(tx);
|
|
||||||
self.emit('unconfirmed', tx);
|
self.emit('unconfirmed', tx);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.destroy = function destroy() {
|
Wallet.prototype.destroy = function destroy() {
|
||||||
|
if (!this.provider)
|
||||||
|
return;
|
||||||
|
|
||||||
this.provider.destroy();
|
this.provider.destroy();
|
||||||
this.provider = null;
|
this.provider = null;
|
||||||
};
|
};
|
||||||
@ -216,9 +218,6 @@ Wallet.prototype.removeKey = function removeKey(key) {
|
|||||||
else if (bcoin.hd.publicKey.isExtended(key))
|
else if (bcoin.hd.publicKey.isExtended(key))
|
||||||
key = bcoin.hd.publicKey(key);
|
key = bcoin.hd.publicKey(key);
|
||||||
|
|
||||||
if (key instanceof bcoin.keypair)
|
|
||||||
key = key.hd;
|
|
||||||
|
|
||||||
if (key instanceof bcoin.hd.privateKey)
|
if (key instanceof bcoin.hd.privateKey)
|
||||||
key = key.hdPublicKey;
|
key = key.hdPublicKey;
|
||||||
|
|
||||||
@ -428,7 +427,7 @@ Wallet.prototype.parsePath = function parsePath(path) {
|
|||||||
Wallet.prototype.setReceiveDepth = function setReceiveDepth(depth) {
|
Wallet.prototype.setReceiveDepth = function setReceiveDepth(depth) {
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
if (depth <= this.receiveDepth)
|
if (!(depth > this.receiveDepth))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = this.receiveDepth; i < depth; i++)
|
for (i = this.receiveDepth; i < depth; i++)
|
||||||
@ -445,7 +444,7 @@ Wallet.prototype.setReceiveDepth = function setReceiveDepth(depth) {
|
|||||||
Wallet.prototype.setChangeDepth = function setChangeDepth(depth) {
|
Wallet.prototype.setChangeDepth = function setChangeDepth(depth) {
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
if (depth <= this.changeDepth)
|
if (!(depth > this.changeDepth))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = this.changeDepth; i < depth; i++)
|
for (i = this.changeDepth; i < depth; i++)
|
||||||
@ -674,33 +673,30 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx) {
|
|||||||
var depth = this.getOutputDepth(tx);
|
var depth = this.getOutputDepth(tx);
|
||||||
var res = false;
|
var res = false;
|
||||||
|
|
||||||
if (depth.changeDepth >= this.changeDepth) {
|
if (this.setChangeDepth(depth.changeDepth + 1))
|
||||||
this.setChangeDepth(depth.changeDepth + 1);
|
|
||||||
res = true;
|
res = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (depth.receiveDepth >= this.receiveDepth) {
|
if (this.setReceiveDepth(depth.receiveDepth + 1))
|
||||||
this.setReceiveDepth(depth.receiveDepth + 1);
|
|
||||||
res = true;
|
res = true;
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.scan = function scan(txByAddress, callback) {
|
Wallet.prototype.scan = function scan(txByAddress, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var res = false;
|
||||||
|
|
||||||
return this._scan({}, txByAddress, function(err, depth) {
|
return this._scan({}, txByAddress, function(err, depth) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (depth.changeDepth >= self.changeDepth)
|
if (self.setChangeDepth(depth.changeDepth + 1))
|
||||||
self.setChangeDepth(depth.changeDepth + 1);
|
res = true;
|
||||||
|
|
||||||
if (depth.receiveDepth >= self.receiveDepth)
|
if (self.setReceiveDepth(depth.receiveDepth + 1))
|
||||||
self.setReceiveDepth(depth.receiveDepth + 1);
|
res = true;
|
||||||
|
|
||||||
return callback(null, self);
|
return callback(null, res);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -822,11 +818,25 @@ Wallet.prototype.getBalance = function getBalance(callback) {
|
|||||||
return this.provider.getBalance(callback);
|
return this.provider.getBalance(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getLast = function getLast(callback) {
|
Wallet.prototype.getLastTime = function getLastTime(callback) {
|
||||||
if (!this.provider)
|
if (!this.provider)
|
||||||
return callback(new Error('No wallet provider available.'));
|
return callback(new Error('No wallet provider available.'));
|
||||||
|
|
||||||
return this.provider.getLast(callback);
|
return this.provider.getLastTime(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.getLast = function getLast(limit, callback) {
|
||||||
|
if (!this.provider)
|
||||||
|
return callback(new Error('No wallet provider available.'));
|
||||||
|
|
||||||
|
return this.provider.getLast(limit, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.getTimeRange = function getTimeRange(options, callback) {
|
||||||
|
if (!this.provider)
|
||||||
|
return callback(new Error('No wallet provider available.'));
|
||||||
|
|
||||||
|
return this.provider.getTimeRange(options, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
|
Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
|
||||||
@ -957,9 +967,6 @@ Wallet.prototype.toJSON = function toJSON() {
|
|||||||
receiveDepth: this.receiveDepth,
|
receiveDepth: this.receiveDepth,
|
||||||
changeDepth: this.changeDepth,
|
changeDepth: this.changeDepth,
|
||||||
master: this.master.toJSON(this.options.passphrase),
|
master: this.master.toJSON(this.options.passphrase),
|
||||||
// Store account key to:
|
|
||||||
// a. save ourselves derivations.
|
|
||||||
// b. allow deriving of addresses without decrypting the master key.
|
|
||||||
accountKey: this.accountKey.xpubkey,
|
accountKey: this.accountKey.xpubkey,
|
||||||
addressMap: this.addressMap,
|
addressMap: this.addressMap,
|
||||||
keys: this.keys.map(function(key) {
|
keys: this.keys.map(function(key) {
|
||||||
@ -993,10 +1000,15 @@ Wallet._fromJSON = function _fromJSON(json, passphrase) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.fromJSON = function fromJSON(json, passphrase) {
|
||||||
|
return new Wallet(Wallet._fromJSON(json, passphrase));
|
||||||
|
};
|
||||||
|
|
||||||
// For updating the address table quickly
|
// For updating the address table quickly
|
||||||
// without decrypting the master key.
|
// without decrypting the master key.
|
||||||
Wallet.sync = function sync(json, options) {
|
Wallet._syncDepth = function sync(json, options) {
|
||||||
var master, wallet;
|
var master, wallet;
|
||||||
|
var res = false;
|
||||||
|
|
||||||
assert.equal(json.v, 3);
|
assert.equal(json.v, 3);
|
||||||
assert.equal(json.name, 'wallet');
|
assert.equal(json.name, 'wallet');
|
||||||
@ -1008,17 +1020,26 @@ Wallet.sync = function sync(json, options) {
|
|||||||
json.master = json.accountKey;
|
json.master = json.accountKey;
|
||||||
wallet = new Wallet(json);
|
wallet = new Wallet(json);
|
||||||
|
|
||||||
if (options.txs != null) {
|
if (!wallet._initialized)
|
||||||
options.txs.forEach(function(tx) {
|
return;
|
||||||
wallet.syncOutputDepth(tx);
|
|
||||||
});
|
if (options.tx != null) {
|
||||||
|
if (wallet.syncOutputDepth(options.tx))
|
||||||
|
res = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.receiveDepth != null)
|
if (options.receiveDepth != null) {
|
||||||
wallet.setReceiveDepth(options.receiveDepth);
|
if (wallet.setReceiveDepth(options.receiveDepth))
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.changeDepth != null)
|
if (options.changeDepth != null) {
|
||||||
wallet.setChangeDepth(options.changeDepth);
|
if (wallet.setChangeDepth(options.changeDepth))
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
return;
|
||||||
|
|
||||||
wallet = wallet.toJSON();
|
wallet = wallet.toJSON();
|
||||||
wallet.master = master;
|
wallet.master = master;
|
||||||
@ -1026,8 +1047,27 @@ Wallet.sync = function sync(json, options) {
|
|||||||
return wallet;
|
return wallet;
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.fromJSON = function fromJSON(json, passphrase) {
|
Wallet.syncOutputDepth = function syncOutputDepth(json, tx) {
|
||||||
return new Wallet(Wallet._fromJSON(json, passphrase));
|
return Wallet._syncDepth(json, { tx: tx });
|
||||||
|
};
|
||||||
|
|
||||||
|
Wallet.setReceiveDepth = function setReceiveDepth(json, receiveDepth) {
|
||||||
|
return Wallet._syncDepth(json, {
|
||||||
|
receiveDepth: receiveDepth || 0
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Wallet.setChangeDepth = function setChangeDepth(json, changeDepth) {
|
||||||
|
return Wallet._syncDepth(json, {
|
||||||
|
changeDepth: changeDepth || 0
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Wallet.setDepth = function setDepth(json, receiveDepth, changeDepth) {
|
||||||
|
return Wallet._syncDepth(json, {
|
||||||
|
receiveDepth: receiveDepth || 0,
|
||||||
|
changeDepth: changeDepth || 0
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -166,22 +166,7 @@ WalletDB.prototype._init = function _init() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
utils.forEachSerial(map.output, function(id, next) {
|
utils.forEachSerial(map.output, function(id, next) {
|
||||||
self.getJSON(id, function(err, json) {
|
self.syncOutputDepth(id, tx, next);
|
||||||
if (err) {
|
|
||||||
self.emit('error', err);
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate new addresses if necessary.
|
|
||||||
json = bcoin.wallet.sync(json, { txs: [tx] });
|
|
||||||
|
|
||||||
self.saveJSON(id, json, function(err) {
|
|
||||||
if (err)
|
|
||||||
return next(err);
|
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
@ -189,29 +174,53 @@ WalletDB.prototype._init = function _init() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletDB.prototype.syncDepth = function syncDepth(id, changeDepth, receiveDepth, callback) {
|
WalletDB.prototype.syncOutputDepth = function syncOutputDepth(id, tx, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
if (!receiveDepth)
|
this.getJSON(id, function(err, json) {
|
||||||
receiveDepth = 0;
|
|
||||||
|
|
||||||
if (!changeDepth)
|
|
||||||
changeDepth = 0;
|
|
||||||
|
|
||||||
self.getJSON(id, function(err, json) {
|
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
// Allocate new addresses if necessary.
|
// Allocate new addresses if necessary.
|
||||||
json = bcoin.wallet.sync(json, {
|
json = bcoin.wallet.syncOutputDepth(json, tx);
|
||||||
receiveDepth: receiveDepth,
|
|
||||||
changeDepth: changeDepth
|
if (!json)
|
||||||
});
|
return callback();
|
||||||
|
|
||||||
self.saveJSON(id, json, function(err) {
|
self.saveJSON(id, json, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
self.emit('sync depth', id, receiveDepth, changeDepth);
|
|
||||||
|
self.emit('sync output depth', id, tx);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
WalletDB.prototype.setDepth = function setDepth(id, receive, change, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
|
this.getJSON(id, function(err, json) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
// Allocate new addresses if necessary.
|
||||||
|
json = bcoin.wallet.setDepth(json, receive, change);
|
||||||
|
|
||||||
|
if (!json)
|
||||||
|
return callback();
|
||||||
|
|
||||||
|
self.saveJSON(id, json, function(err) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
self.emit('set depth', id, receive, change);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -477,6 +486,7 @@ WalletDB.prototype.update = function update(wallet, address) {
|
|||||||
if (err)
|
if (err)
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
|
|
||||||
|
// XXX might have to encrypt key - slow
|
||||||
self._saveDB(wallet.id, wallet.toJSON(), function(err) {
|
self._saveDB(wallet.id, wallet.toJSON(), function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
@ -520,10 +530,22 @@ WalletDB.prototype.getBalance = function getBalance(id, callback) {
|
|||||||
return this.tx.getBalanceByAddress(id, callback);
|
return this.tx.getBalanceByAddress(id, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletDB.prototype.getLast = function getLast(id, callback) {
|
WalletDB.prototype.getLastTime = function getLastTime(id, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
id = id.id || id;
|
id = id.id || id;
|
||||||
return this.tx.getLast(id, callback);
|
return this.tx.getLastTime(id, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
WalletDB.prototype.getLast = function getLast(id, limit, callback) {
|
||||||
|
var self = this;
|
||||||
|
id = id.id || id;
|
||||||
|
return this.tx.getLast(id, limit, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
WalletDB.prototype.getTimeRange = function getTimeRange(id, options, callback) {
|
||||||
|
var self = this;
|
||||||
|
id = id.id || id;
|
||||||
|
return this.tx.getTimeRange(id, options, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletDB.prototype.fillTX = function fillTX(tx, callback) {
|
WalletDB.prototype.fillTX = function fillTX(tx, callback) {
|
||||||
@ -650,8 +672,16 @@ Provider.prototype.getBalance = function getBalance(callback) {
|
|||||||
return this.db.getBalance(this.id, callback);
|
return this.db.getBalance(this.id, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Provider.prototype.getLast = function getLast(callback) {
|
Provider.prototype.getLastTime = function getLastTime(callback) {
|
||||||
return this.db.getLast(this.id, callback);
|
return this.db.getLastTime(this.id, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
Provider.prototype.getLast = function getLast(limit, callback) {
|
||||||
|
return this.db.getLast(this.id, limit, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
Provider.prototype.getTimeRange = function getTimeRange(options, callback) {
|
||||||
|
return this.db.getTimeRange(this.id, options, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Provider.prototype.getTX = function getTX(hash, callback) {
|
Provider.prototype.getTX = function getTX(hash, callback) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user