This commit is contained in:
Christopher Jeffrey 2016-03-24 03:44:43 -07:00
parent b4b4e8b6cc
commit 1db0954c83
6 changed files with 74 additions and 140 deletions

View File

@ -36,19 +36,10 @@ function ChainDB(chain, options) {
this.size = 0;
this.fd = null;
this.loaded = false;
this.fsync = !!options.fsync;
this.keepBlocks = options.keepBlocks || 288;
this.prune = !!options.prune;
// Keep track of block hashes in a
// bloom filter to avoid DB lookups.
// 1% false positive rate for 800k blocks
// http://hur.st/bloomfilter?n=800000&p=0.01 (m=936kb, k=7)
// 10% false positive rate for 800k blocks
// http://hur.st/bloomfilter?n=800000&p=0.10 (m=468kb, k=3)
// this.bloom = new bcoin.bloom(937 * 1024, 7, 0xdeadbeef);
// Need to cache up to the retarget interval
// if we're going to be checking the damn
// target all the time.
@ -177,9 +168,6 @@ ChainDB.prototype.getHeight = function getHeight(hash, callback) {
if (this.cacheHash.has(hash))
return callback(null, this.cacheHash.get(hash).height);
// if (!this.bloom.test(hash, 'hex'))
// return callback(null, -1);
this.db.get('c/b/' + hash, function(err, height) {
if (err && err.type !== 'NotFoundError')
return callback(err);
@ -355,13 +343,9 @@ ChainDB.prototype.save = function save(entry, block, callback) {
assert(entry.height >= 0);
// Cache the past 1001 blocks in memory
// (necessary for isSuperMajority)
this.addCache(entry);
// this.bloom.add(entry.hash, 'hex');
batch = this.batch();
batch = this.db.batch();
height = new Buffer(4);
utils.writeU32(height, entry.height, 0);
@ -409,7 +393,7 @@ ChainDB.prototype.connect = function connect(block, callback) {
if (!entry)
return callback();
batch = self.batch();
batch = self.db.batch();
batch.put('c/h/' + pad32(entry.height), new Buffer(entry.hash, 'hex'));
batch.put('c/t', new Buffer(entry.hash, 'hex'));
@ -442,7 +426,7 @@ ChainDB.prototype.disconnect = function disconnect(block, callback) {
if (!entry)
return callback();
batch = self.batch();
batch = self.db.batch();
batch.del('c/h/' + pad32(entry.height));
batch.put('c/t', new Buffer(entry.prevBlock, 'hex'));
@ -507,7 +491,7 @@ ChainDB.prototype.reset = function reset(block, callback) {
if (!tip)
return callback();
batch = self.batch();
batch = self.db.batch();
if (tip.hash === entry.hash) {
batch.put('c/t', new Buffer(tip.hash, 'hex'));
@ -547,12 +531,6 @@ ChainDB.prototype.has = function has(height, callback) {
});
};
ChainDB.prototype.batch = function batch() {
if (this.fsync)
return new utils.SyncBatch(this.db);
return this.db.batch();
};
ChainDB.prototype.saveBlock = function saveBlock(block, batch, callback) {
if (this.options.spv)
return callback();
@ -613,7 +591,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) {
tx.inputs.forEach(function(input) {
var address;
if (input.isCoinbase())
if (tx.isCoinbase())
return;
assert(input.output);
@ -685,7 +663,7 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(hash, batch, callba
tx.inputs.forEach(function(input) {
var address;
if (input.isCoinbase())
if (tx.isCoinbase())
return;
assert(input.output);
@ -1283,10 +1261,10 @@ ChainDB.prototype._pruneBlock = function _pruneBlock(block, batch, callback) {
batch.put('b/q/' + futureHeight, block.hash());
block.txs.forEach(function(tx) {
tx.inputs.forEach(function(input) {
if (input.isCoinbase())
return;
if (tx.isCoinbase())
return;
tx.inputs.forEach(function(input) {
assert(input.output);
batch.put('u/x/'

View File

@ -56,9 +56,9 @@ function Coin(tx, index) {
assert(utils.isFinite(this.height));
assert(this.value instanceof bn);
assert(this.script instanceof bcoin.script);
assert(typeof this.hash === 'string');
assert(utils.isFinite(this.index));
assert(typeof this.coinbase === 'boolean');
// assert(typeof this.hash === 'string');
// assert(utils.isFinite(this.index));
}
utils.inherits(Coin, bcoin.output);
@ -120,7 +120,7 @@ Coin.prototype.inspect = function inspect() {
value: utils.btc(this.value),
script: bcoin.script.format(this.script),
coinbase: this.coinbase,
hash: utils.revHex(this.hash),
hash: this.hash ? utils.revHex(this.hash) : null,
index: this.index,
address: this.getAddress()
};
@ -133,7 +133,7 @@ Coin.prototype.toJSON = function toJSON() {
value: utils.btc(this.value),
script: utils.toHex(this.script.encode()),
coinbase: this.coinbase,
hash: utils.revHex(this.hash),
hash: this.hash ? utils.revHex(this.hash) : null,
index: this.index
};
};
@ -145,7 +145,7 @@ Coin._fromJSON = function _fromJSON(json) {
value: utils.satoshi(json.value),
script: new bcoin.script(new Buffer(json.script, 'hex')),
coinbase: json.coinbase,
hash: utils.revHex(json.hash),
hash: json.hash ? utils.revHex(json.hash) : null,
index: json.index
};
};

View File

@ -1495,6 +1495,8 @@ TXPool.prototype.getCoin = function getCoin(hash, index, callback) {
try {
coin = bcoin.coin.fromExtended(coin);
coin.hash = hash;
coin.index = index;
} catch (e) {
return callback(e);
}

View File

@ -428,19 +428,15 @@ utils.isEqual = function isEqual(a, b) {
return true;
};
utils.nextTick = function nextTick(fn) {
if (typeof setImmediate === 'function') {
setImmediate(fn);
return;
}
if (typeof process === 'object' && process.nextTick) {
process.nextTick(fn);
return;
}
setTimeout(fn, 1);
};
if (typeof setImmediate === 'function') {
utils.nextTick = setImmediate;
} else if (!utils.isBrowser) {
utils.nextTick = process.nextTick;
} else {
utils.nextTick = function nextTick(fn) {
setTimeout(fn, 1);
};
}
function RequestCache() {
this.map = {};
@ -1883,36 +1879,6 @@ utils.toMap = function toMap(arr) {
}, {});
};
function SyncBatch(db) {
this.db = db;
this.ops = [];
}
SyncBatch.prototype.put = function put(key, value) {
assert(this.ops, 'Batch was already written.');
this.ops.push({ type: 'put', key: key, value: value });
};
SyncBatch.prototype.del = function del(key) {
assert(this.ops, 'Batch was already written.');
this.ops.push({ type: 'del', key: key });
};
SyncBatch.prototype.write = function write(callback) {
assert(this.ops, 'Batch was already written.');
this.db.batch(this.ops, { sync: true }, callback);
this.ops.length = 0;
delete this.ops;
delete this.db;
};
SyncBatch.prototype.clear = function clear() {
assert(this.ops, 'Batch was already written.');
this.ops.length = 0;
};
utils.SyncBatch = SyncBatch;
if (utils.isBrowser) {
bn.prototype.toBuffer = function toBuffer(order, size) {
return this.toArrayLike(Buffer, order, size);

View File

@ -1,8 +1,8 @@
var assert = require('assert');
var bn = require('bn.js');
var bcoin = require('../');
var constants = bcoin.protocol.constants;
var utils = bcoin.utils;
var assert = utils.assert;
describe('Wallet', function() {
process.env.BCOIN_DB = 'memdown';
@ -97,40 +97,31 @@ describe('Wallet', function() {
var peer = { sendReject: function() {} };
node.mempool.addTX(fake, peer, function(err) {
if (err)
throw err;
assert(!err);
assert.noError(err);
node.mempool.addTX(t4, peer, function(err) {
assert(!err);
assert.noError(err);
node.mempool.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '0');
node.mempool.addTX(t1, peer, function(err) {
if (err)
throw err;
assert.noError(err);
node.mempool.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '60000');
node.mempool.addTX(t2, peer, function(err) {
if (err)
throw err;
assert(!err);
assert.noError(err);
node.mempool.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '50000');
node.mempool.addTX(t3, peer, function(err) {
assert(!err);
assert.noError(err);
node.mempool.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '22000');
node.mempool.addTX(f1, peer, function(err) {
if (err)
throw err;
assert(!err);
assert.noError(err);
node.mempool.getBalance(function(err, balance) {
if (err)
throw err;
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '20000');
node.mempool.getAll(function(err, txs) {
assert(txs.some(function(tx) {

View File

@ -1,8 +1,8 @@
var assert = require('assert');
var bn = require('bn.js');
var bcoin = require('../');
var constants = bcoin.protocol.constants;
var utils = bcoin.utils;
var assert = utils.assert;
var dummyInput = {
prevout: {
@ -47,7 +47,7 @@ describe('Wallet', function() {
flags |= bcoin.protocol.constants.flags.VERIFY_WITNESS;
wdb.create({ witness: witness }, function(err, w) {
assert(!err);
assert.noError(err);
if (witness)
assert(bcoin.address.parse(w.getAddress()).type === 'witnesspubkeyhash');
@ -133,9 +133,9 @@ describe('Wallet', function() {
it('should have TX pool and be serializable', function(cb) {
wdb.create({}, function(err, w) {
assert(!err);
assert.noError(err);
wdb.create({}, function(err, f) {
assert(!err);
assert.noError(err);
// Coinbase
var t1 = bcoin.mtx().addOutput(w, 50000).addOutput(w, 1000);
@ -182,30 +182,30 @@ describe('Wallet', function() {
// wdb.addTX(fake);
wdb.addTX(fake, function(err) {
assert(!err);
assert.noError(err);
wdb.addTX(t4, function(err) {
assert(!err);
assert.noError(err);
w.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '22500');
wdb.addTX(t1, function(err) {
w.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '73000');
wdb.addTX(t2, function(err) {
assert(!err);
assert.noError(err);
w.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '47000');
wdb.addTX(t3, function(err) {
assert(!err);
assert.noError(err);
w.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '22000');
wdb.addTX(f1, function(err) {
assert(!err);
assert.noError(err);
w.getBalance(function(err, balance) {
assert(!err);
assert.noError(err);
assert.equal(balance.toString(10), '11000');
w.getAll(function(err, txs) {
assert(txs.some(function(tx) {
@ -236,9 +236,9 @@ describe('Wallet', function() {
it('should fill tx with inputs', function(cb) {
wdb.create({}, function(err, w1) {
assert(!err);
assert.noError(err);
wdb.create({}, function(err, w2) {
assert(!err);
assert.noError(err);
// Coinbase
var t1 = bcoin.mtx()
@ -251,12 +251,12 @@ describe('Wallet', function() {
// Fake TX should temporarly change output
wdb.addTX(t1, function(err) {
assert(!err);
assert.noError(err);
// Create new transaction
var t2 = bcoin.mtx().addOutput(w2, 5460);
w1.fill(t2, function(err) {
assert(!err);
assert.noError(err);
w1.sign(t2);
assert(t2.verify());
@ -281,11 +281,11 @@ describe('Wallet', function() {
it('should sign multiple inputs using different keys', function(cb) {
wdb.create({}, function(err, w1) {
assert(!err);
assert.noError(err);
wdb.create({}, function(err, w2) {
assert(!err);
assert.noError(err);
wdb.create({}, function(err, to) {
assert(!err);
assert.noError(err);
// Coinbase
var t1 = bcoin.mtx()
@ -308,9 +308,9 @@ describe('Wallet', function() {
// Fake TX should temporarly change output
wdb.addTX(t1, function(err) {
assert(!err);
assert.noError(err);
wdb.addTX(t2, function(err) {
assert(!err);
assert.noError(err);
// Create our tx with an output
var tx = bcoin.mtx();
@ -320,9 +320,9 @@ describe('Wallet', function() {
var total = cost.add(new bn(constants.tx.minFee));
w1.getCoins(function(err, coins1) {
assert(!err);
assert.noError(err);
w2.getCoins(function(err, coins2) {
assert(!err);
assert.noError(err);
// Add dummy output (for `left`) to calculate maximum TX size
tx.addOutput(w1, new bn(0));
@ -386,13 +386,13 @@ describe('Wallet', function() {
};
wdb.create(utils.merge({}, options), function(err, w1) {
assert(!err);
assert.noError(err);
wdb.create(utils.merge({}, options), function(err, w2) {
assert(!err);
assert.noError(err);
wdb.create(utils.merge({}, options), function(err, w3) {
assert(!err);
assert.noError(err);
wdb.create({}, function(err, receive) {
assert(!err);
assert.noError(err);
w1.addKey(w2);
w1.addKey(w3);
@ -439,11 +439,11 @@ describe('Wallet', function() {
assert.equal(w1.receiveDepth, 1);
wdb.addTX(utx, function(err) {
assert(!err);
assert.noError(err);
wdb.addTX(utx, function(err) {
assert(!err);
assert.noError(err);
wdb.addTX(utx, function(err) {
assert(!err);
assert.noError(err);
assert.equal(w1.receiveDepth, 2);
assert.equal(w1.changeDepth, 1);
@ -459,9 +459,7 @@ describe('Wallet', function() {
send.addOutput({ address: receive.getAddress(), value: 5460 });
assert(!send.verify(null, true, flags));
w1.fill(send, { m: w1.m, n: w1.n }, function(err) {
if (err)
throw err;
assert(!err);
assert.noError(err);
w1.sign(send);
@ -482,11 +480,11 @@ describe('Wallet', function() {
send.height = 1;
wdb.addTX(send, function(err) {
assert(!err);
assert.noError(err);
wdb.addTX(send, function(err) {
assert(!err);
assert.noError(err);
wdb.addTX(send, function(err) {
assert(!err);
assert.noError(err);
assert.equal(w1.receiveDepth, 2);
assert.equal(w1.changeDepth, 2);
@ -539,9 +537,8 @@ describe('Wallet', function() {
});
it('should have gratuitous dump', function(cb) {
return cb();
bcoin.walletdb().dump(function(err, records) {
assert(!err);
assert.noError(err);
console.log(records);
setTimeout(cb, 200);
});