use leveldb iterators for getting by address.

This commit is contained in:
Christopher Jeffrey 2016-02-24 01:38:36 -08:00
parent 6a644be03f
commit 8a3b0161c0

View File

@ -513,6 +513,96 @@ BlockDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, call
});
};
BlockDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, options, callback) {
var self = this;
var coins = [];
if (!callback) {
callback = options;
options = {};
}
if (typeof addresses === 'string')
addresses = [addresses];
addresses = utils.uniqs(addresses);
utils.forEach(addresses, function(address, done) {
var iter = self.index.db.iterator({
gte: 'u/a/' + address,
lte: 'u/a/' + address + '~',
keys: true,
values: true,
fillCache: true,
keyAsBuffer: false,
valueAsBuffer: true
});
(function next() {
iter.next(function(err, key, value) {
var record, parts, hash, index;
if (err) {
return iter.end(function() {
done(err);
});
}
// iter.end() here?
if (!key)
return done();
parts = key.split('/').slice(3);
hash = parts[0];
index = +parts[1];
record = self.parseOffset(value);
self.data.getAsync(record.size, record.offset, function(err, data) {
var coin;
if (err) {
return iter.end(function() {
done(err);
});
}
if (!data)
return done();
try {
data = self.parser.parseOutput(data);
} catch (e) {
return iter.end(function() {
done(e);
});
}
coin = bcoin.coin({
version: 1,
hash: hash,
index: index,
height: record.height,
script: data.script,
value: data.value,
spent: false
});
if (self.options.cache)
self.cache.unspent.set(id, coin);
coins.push(coin);
next();
});
});
})();
}, function(err) {
if (err)
return callback(err);
return callback(null, coins);
});
};
BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, callback) {
var self = this;
var pending = 0;
@ -640,23 +730,25 @@ BlockDB.prototype.getCoin = function getCoin(hash, index, callback) {
if (err)
return callback(err);
if (data) {
try {
data = self.parser.parseOutput(data);
} catch (e) {
return callback(e);
}
coin = bcoin.coin({
version: 1,
hash: hash,
index: index,
height: record.height,
script: data.script,
value: data.value,
spent: false
});
if (!data)
return callback();
try {
data = self.parser.parseOutput(data);
} catch (e) {
return callback(e);
}
coin = bcoin.coin({
version: 1,
hash: hash,
index: index,
height: record.height,
script: data.script,
value: data.value,
spent: false
});
return callback(null, coin);
});
});
@ -688,6 +780,119 @@ BlockDB.prototype.getTXByAddress = function getTXByAddress(addresses, callback)
});
};
BlockDB.prototype.getTXByAddress = function getTXByAddress(addresses, options, callback) {
var self = this;
var txs = [];
var have = {};
if (!callback) {
callback = options;
options = {};
}
if (typeof addresses === 'string')
addresses = [addresses];
addresses = utils.uniqs(addresses);
utils.forEach(addresses, function(address, done) {
var iter = self.index.db.iterator({
gte: 't/a/' + address,
lte: 't/a/' + address + '~',
keys: true,
values: true,
fillCache: true,
keyAsBuffer: false,
valueAsBuffer: true
});
(function next() {
iter.next(function(err, key, value) {
var record, parts, hash, index;
if (err) {
return iter.end(function() {
done(err);
});
}
// iter.end() here?
if (!key)
return done();
parts = key.split('/').slice(3);
hash = parts[0];
record = self.parseOffset(value);
if (addresses.length > 1) {
if (have[hash])
return next();
have[hash] = true;
}
if (self.options.cache && self.cache.tx.has(hash)) {
txs.push(self.cache.tx.get(hash));
return done();
}
self.data.getAsync(record.size, record.offset, function(err, data) {
var coin;
if (err) {
return iter.end(function() {
done(err);
});
}
if (!data)
return next();
try {
tx = self.parser.parseTX(data);
tx = new bcoin.tx(tx);
} catch (e) {
return iter.end(function() {
done(e);
});
}
return self._getEntry(record.height, function(err, entry) {
if (err) {
return iter.end(function() {
done(err);
});
}
tx.network = true;
tx.height = record.height;
if (entry) {
tx.ts = entry.ts;
tx.block = entry.hash;
}
txs.push(tx);
if (self.options.cache)
self.cache.tx.set(hash, tx);
if (self.options.paranoid && tx.hash('hex') !== hash)
return next(new Error('BlockDB is corrupt. All is lost.'));
next();
});
});
});
})();
}, function(err) {
if (err)
return callback(err);
return callback(null, txs);
});
};
BlockDB.prototype._getTXByAddress = function _getTXByAddress(address, callback) {
var self = this;
var pending = 0;
@ -711,11 +916,11 @@ BlockDB.prototype._getTXByAddress = function _getTXByAddress(address, callback)
pending++;
if (self.options.cache && self.cache.tx.has(hash)) {
coins.push(self.cache.tx.get(hash));
txs.push(self.cache.tx.get(hash));
pending--;
if (done) {
if (!pending)
return callback(null, coins);
return callback(null, txs);
}
return;
}