deployments.

This commit is contained in:
Christopher Jeffrey 2016-04-17 12:09:30 -07:00
parent 69436cfd16
commit f3c2134dfa
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
9 changed files with 315 additions and 251 deletions

View File

@ -11,24 +11,31 @@ var utils = require('./utils');
* Bloom Filter
* @exports Bloom
* @constructor
* @param {Number} size - Filter size in bytes.
* @param {Number|Bufer} size - Filter size in bytes, or filter itself.
* @param {Number} n - Number of hash functions.
* @param {Number} tweak - Seed value.
* @property {Buffer} filter
* @property {Number} size
* @property {Number} n
* @property {Number} tweak
* @property {Number} update - Update flag (see {@link constants.filterFlags}).
*/
function Bloom(size, n, tweak) {
function Bloom(size, n, tweak, update) {
if (!(this instanceof Bloom))
return new Bloom(size, n, tweak);
return new Bloom(size, n, tweak, update);
if (Buffer.isBuffer(size)) {
this.filter = size;
this.size = this.filter.length * 8;
} else {
this.filter = new Buffer(Math.ceil(size / 8));
this.size = size;
}
this.filter = new Buffer(Math.ceil(size / 8));
this.size = size;
this.n = n;
this.tweak = tweak;
this.update = null;
this.update = update;
this.reset();
}

View File

@ -38,6 +38,7 @@ var VerifyError = utils.VerifyError;
* @property {ChainBlock?} tip
* @property {Number} height
* @property {Boolean} segwitActive
* @property {Boolean} csvActive
* @property {Object} orphan - Orphan map.
* @emits Chain#open
* @emits Chain#error
@ -78,6 +79,7 @@ function Chain(options) {
this.tip = null;
this.height = -1;
this.segwitActive = null;
this.csvActive = null;
this.orphan = {
map: {},
@ -218,11 +220,14 @@ Chain.prototype._init = function _init() {
if (self.bestHeight === -1)
network.height = tip.height;
self.isSegwitActive(function(err, result) {
self._getInitialState(function(err) {
if (err)
return self.emit('error', err);
if (result)
if (self.csvActive)
bcoin.debug('CSV is active.');
if (self.segwitActive)
bcoin.debug('Segwit is active.');
self.loaded = true;
@ -463,11 +468,8 @@ Chain.prototype._verifyContext = function _verifyContext(block, prev, callback)
Chain.prototype._verify = function _verify(block, prev, callback) {
var self = this;
var flags = constants.flags.MANDATORY_VERIFY_FLAGS;
var lockFlags = constants.flags.MANDATORY_LOCKTIME_FLAGS;
var height, ts, i, tx, coinbaseHeight;
var medianTime, segwit, commitmentHash;
var ret = {};
var height, ts, i, tx, medianTime, commitmentHash;
function done(err, result) {
prev.free();
@ -478,11 +480,11 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
return done(new VerifyError(block, 'invalid', ret.reason, ret.score));
if (this.options.spv || block.type !== 'block')
return done();
return done(null, constants.flags.MANDATORY_VERIFY_FLAGS);
// Skip the genesis block
if (block.isGenesis())
return done(null, flags);
return done(null, constants.flags.MANDATORY_VERIFY_FLAGS);
// Ensure it's not an orphan
if (!prev)
@ -502,103 +504,26 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
if (block.bits !== self.getTarget(prev, block))
return done(new VerifyError(block, 'invalid', 'bad-diffbits', 100));
// For some reason bitcoind has p2sh in the
// mandatory flags by default, when in reality
// it wasn't activated until march 30th 2012.
// The first p2sh output and redeem script
// appeared on march 7th 2012, only it did
// not have a signature. See:
// 6a26d2ecb67f27d1fa5524763b49029d7106e91e3cc05743073461a719776192
// 9c08a4d78931342b37fd5f72900fb9983087e6f46c4a097d8a1f52c74e28eaf6
if (block.ts < constants.block.BIP16_TIME)
flags &= ~constants.flags.VERIFY_P2SH;
self._checkDeployments(block, prev, function(err, state) {
if (err)
return done(err);
// Only allow version 2 blocks (coinbase height)
// once the majority of blocks are using it.
if (block.version < 2 && prev.isOutdated(2))
return done(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Expose the state of csv and segwit globally.
self.csvActive = state.csv;
self.segwitActive = state.segwit;
// Only allow version 3 blocks (sig validation)
// once the majority of blocks are using it.
if (block.version < 3 && prev.isOutdated(3))
return done(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Only allow version 4 blocks (checklocktimeverify)
// once the majority of blocks are using it.
if (block.version < 4 && prev.isOutdated(4))
return done(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Only allow version 5 blocks (segwit)
// once the majority of blocks are using it.
if (network.segwitHeight !== -1 && height >= network.segwitHeight) {
if (block.version < 5 && prev.isOutdated(5))
return done(new VerifyError(block, 'obsolete', 'bad-version', 0));
}
// Only allow version 8 blocks (locktime median past)
// once the majority of blocks are using it.
// if (block.version < 8 && prev.isOutdated(8))
// return done(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Make sure the height contained in the coinbase is correct.
if (network.block.bip34height !== -1 && height >= network.block.bip34height) {
if (block.version >= 2 && prev.isUpgraded(2))
coinbaseHeight = true;
}
// Signature validation is now enforced (bip66)
if (block.version >= 3 && prev.isUpgraded(3))
flags |= constants.flags.VERIFY_DERSIG;
// CHECKLOCKTIMEVERIFY is now usable (bip65)
if (block.version >= 4 && prev.isUpgraded(4))
flags |= constants.flags.VERIFY_CHECKLOCKTIMEVERIFY;
// Segregrated witness is now usable (bip141 - segnet3)
if (network.segwitHeight !== -1 && height >= network.segwitHeight) {
if (block.version >= 5) {
if (prev.isUpgraded(5)) {
flags |= constants.flags.VERIFY_WITNESS;
segwit = true;
self.segwitActive = true;
} else {
self.segwitActive = false;
}
}
}
// Segregrated witness is now usable (bip141 - segnet4)
if (network.deployments.witness) {
self.getState(prev, 'witness', function(err, state) {
if (err)
return callback(err);
if (state === constants.thresholdStates.ACTIVE) {
flags |= constants.flags.VERIFY_WITNESS;
segwit = true;
self.segwitActive = true;
} else {
self.segwitActive = false;
}
return finish();
});
} else {
finish();
}
function finish() {
// Can't verify any further when merkleblock or headers.
if (block.type !== 'block')
return done(null, flags);
return done(null, state.flags);
// Make sure the height contained in the coinbase is correct.
if (coinbaseHeight) {
if (state.coinbaseHeight) {
if (block.getCoinbaseHeight() !== height)
return done(new VerifyError(block, 'invalid', 'bad-cb-height', 100));
}
if (segwit) {
// Check the commitment hash for segwit.
if (state.segwit) {
commitmentHash = block.commitmentHash;
if (commitmentHash) {
if (!block.witnessNonce) {
@ -616,6 +541,8 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
}
}
// Blocks that do not commit to
// witness data data cannot contain it.
if (!commitmentHash) {
if (block.hasWitness()) {
return done(new VerifyError(block,
@ -626,7 +553,7 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
}
// Get timestamp for tx.isFinal().
ts = (lockFlags & constants.flags.MEDIAN_TIME_PAST) !== 0
ts = (state.lockFlags & constants.flags.MEDIAN_TIME_PAST) !== 0
? medianTime
: block.ts;
@ -644,8 +571,122 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
}
}
return done(null, flags);
return done(null, state.flags);
});
});
};
/**
* Check all deployments on a chain, ranging from p2sh to segwit.
* @private
* @param {Block} block
* @param {ChainBlock} prev
* @param {Function} callback - Returns [{@link VerifyError}, Object].
*/
Chain.prototype._checkDeployments = function _checkDeployments(block, prev, callback) {
var self = this;
var height = prev.height + 1;
var state = {
flags: constants.flags.MANDATORY_VERIFY_FLAGS,
lockFlags: constants.flags.MANDATORY_LOCKTIME_FLAGS,
coinbaseHeight: false,
segwit: false,
csv: false
};
// For some reason bitcoind has p2sh in the
// mandatory flags by default, when in reality
// it wasn't activated until march 30th 2012.
// The first p2sh output and redeem script
// appeared on march 7th 2012, only it did
// not have a signature. See:
// 6a26d2ecb67f27d1fa5524763b49029d7106e91e3cc05743073461a719776192
// 9c08a4d78931342b37fd5f72900fb9983087e6f46c4a097d8a1f52c74e28eaf6
if (block.ts < constants.block.BIP16_TIME)
state.flags &= ~constants.flags.VERIFY_P2SH;
// Only allow version 2 blocks (coinbase height)
// once the majority of blocks are using it.
if (block.version < 2 && prev.isOutdated(2))
return callback(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Only allow version 3 blocks (sig validation)
// once the majority of blocks are using it.
if (block.version < 3 && prev.isOutdated(3))
return callback(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Only allow version 4 blocks (checklocktimeverify)
// once the majority of blocks are using it.
if (block.version < 4 && prev.isOutdated(4))
return callback(new VerifyError(block, 'obsolete', 'bad-version', 0));
// Only allow version 5 blocks (segwit)
// once the majority of blocks are using it.
if (network.segwitHeight !== -1 && height >= network.segwitHeight) {
if (block.version < 5 && prev.isOutdated(5))
return callback(new VerifyError(block, 'obsolete', 'bad-version', 0));
}
// Make sure the height contained in the coinbase is correct.
if (network.block.bip34height !== -1 && height >= network.block.bip34height) {
if (block.version >= 2 && prev.isUpgraded(2))
state.coinbaseHeight = true;
}
// Signature validation is now enforced (bip66)
if (block.version >= 3 && prev.isUpgraded(3))
state.flags |= constants.flags.VERIFY_DERSIG;
// CHECKLOCKTIMEVERIFY is now usable (bip65)
if (block.version >= 4 && prev.isUpgraded(4))
state.flags |= constants.flags.VERIFY_CHECKLOCKTIMEVERIFY;
// Segregrated witness is now usable (bip141 - segnet3)
if (network.segwitHeight !== -1 && height >= network.segwitHeight) {
if (block.version >= 5 && prev.isUpgraded(5)) {
state.flags |= constants.flags.VERIFY_WITNESS;
state.segwit = true;
}
}
utils.serial([
function(next) {
// CHECKSEQUENCEVERIFY and median time
// past locktimes are now usable (bip9 & bip113).
self.isActive(prev, 'csv', function(err, active) {
if (err)
return next(err);
if (active) {
state.flags |= constants.flags.VERIFY_CHECKSEQUENCEVERIFY;
state.lockFlags |= constants.flags.VERIFY_SEQUENCE;
state.lockFlags |= constants.flags.MEDIAN_TIME_PAST;
state.csv = true;
}
return next();
});
},
function(next) {
// Segregrated witness is now usable (bip141 - segnet4)
self.isActive(prev, 'witness', function(err, active) {
if (err)
return next(err);
if (active) {
state.flags |= constants.flags.VERIFY_WITNESS;
state.segwit = true;
}
return next();
});
}
], function(err) {
if (err)
return callback(err);
return callback(null, state);
});
};
@ -2111,6 +2152,29 @@ Chain.prototype.findLocator = function findLocator(locator, callback) {
}, callback);
};
/**
* Check whether a versionbits deployment is active (BIP9: versionbits).
* @example
* chain.isActive(entry, 'witness', callback);
* @see https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki
* @param {ChainBlock} prev - Previous chain entry.
* @param {String} id - Deployment id.
* @param {Function} callback - Returns [Error, Number].
*/
Chain.prototype.isActive = function isActive(prev, id, callback) {
// Optimization for main
if (network.type === 'main' && prev.height < 400000)
return callback(null, false);
this.getState(prev, id, function(err, state) {
if (err)
return callback(err);
return callback(null, state === constants.thresholdStates.ACTIVE);
});
};
/**
* Get chain entry state for a deployment (BIP9: versionbits).
* @example
@ -2292,70 +2356,46 @@ Chain.prototype.computeBlockVersion = function computeBlockVersion(prev, callbac
* A helper function to test whether segwit is active at any
* given time. Since segwit affects almost all of bitcoin, it
* is one deployment that needs to be checked frequently.
* @private
* @param {Function} callback - Returns [Error, Boolean].
*/
Chain.prototype.isSegwitActive = function isSegwitActive(callback, force) {
Chain.prototype._getInitialState = function _getInitialState(callback) {
var self = this;
var unlock;
if (this.segwitActive != null)
return utils.asyncify(callback)(null, this.segwitActive);
if (!network.witness) {
this.segwitActive = false;
return utils.asyncify(callback)(null, false);
}
return utils.nextTick(callback);
if (!this.tip)
return utils.asyncify(callback)(null, false);
// unlock = this._lock(isSegwitActive, [callback], force);
// if (!unlock)
// return;
// callback = utils.wrap(callback, unlock);
if (network.type === 'segnet4') {
return this.tip.getPrevious(function(err, prev) {
if (err)
return callback(err);
return self.getState(prev, 'witness', function(err, state) {
if (err)
return callback(err);
self.segwitActive = state === constants.thresholdStates.ACTIVE;
return callback(null, self.segwitActive);
});
});
}
assert(network.type === 'segnet3');
if (!(network.segwitHeight !== -1 && this.tip.height >= network.segwitHeight))
return utils.asyncify(callback)(null, false);
return utils.nextTick(callback);
return this.tip.getPrevious(function(err, prev) {
if (err)
return callback(err);
if (!prev) {
self.csvActive = false;
self.segwitActive = false;
return callback(null, false);
return callback();
}
prev.ensureAncestors(function(err) {
if (err)
return callback(err);
if (self.tip.version >= 5 && prev.isUpgraded(5)) {
if (err) {
prev.free();
self.segwitActive = true;
return callback(null, true);
return callback(err);
}
self._checkDeployments(self.tip, prev, function(err, state) {
if (err) {
prev.free();
return callback(err);
}
prev.free();
self.segwitActive = false;
return callback(null, false);
self.csvActive = state.csv;
self.segwitActive = state.segwit;
prev.free();
return callback();
});
});
});
};
@ -2375,14 +2415,9 @@ Chain.prototype.isSegwitActive = function isSegwitActive(callback, force) {
* @param {Function} callback - Returns [Error, Boolean].
*/
Chain.prototype.checkFinal = function checkFinal(prev, tx, flags, callback, force) {
Chain.prototype.checkFinal = function checkFinal(prev, tx, flags, callback) {
var height = prev.height + 1;
// var unlock = this._lock(checkFinal, [prev, tx, flags, callback], force);
// if (!unlock)
// return;
// callback = utils.wrap(callback, unlock);
function check(err, ts) {
if (err)
return callback(err);
@ -2490,14 +2525,9 @@ Chain.prototype.evalLocks = function evalLocks(entry, minHeight, minTime, callba
* @param {Function} callback - Returns [Error, Boolean].
*/
Chain.prototype.checkLocks = function checkLocks(tx, flags, entry, callback, force) {
Chain.prototype.checkLocks = function checkLocks(tx, flags, entry, callback) {
var self = this;
// var unlock = this._lock(checkLocks, [tx, flags, entry, callback], force);
// if (!unlock)
// return;
// callback = utils.wrap(callback, unlock);
this.getLocks(tx, flags, entry, function(err, minHeight, minTime) {
if (err)
return callback(err);

View File

@ -302,6 +302,22 @@ ChainBlock.prototype.getMedianTime = function getMedianTime(ancestors) {
return median[median.length / 2 | 0];
};
/**
* Get median time past asynchronously (see {@link ChainBlock#getMedianTime}).
* @param {Function} callback - Returns [Error, Number].
*/
ChainBlock.prototype.getMedianTimeAsync = function getMedianTimeAsync(callback) {
var self = this;
return this.getAncestors(constants.block.MEDIAN_TIMESPAN, function(err, ancestors) {
if (err)
return callback(err);
return callback(null, self.getMedianTime(ancestors));
});
};
/**
* Check isSuperMajority against majorityRejectOutdated.
* @param {Number} version
@ -313,6 +329,20 @@ ChainBlock.prototype.isOutdated = function isOutdated(version, ancestors) {
return this.isSuperMajority(version, network.block.majorityRejectOutdated, ancestors);
};
/**
* Check {@link ChainBlock#isUpgraded asynchronously}.
* @param {Number} version
* @param {Function} callback - Returns [Error, Boolean].
* @returns {Boolean}
*/
ChainBlock.prototype.isOutdatedAsync = function isOutdatedAsync(version, callback) {
return this.isSuperMajorityAsync(
version,
network.block.majorityRejectOutdated,
callback);
};
/**
* Check isSuperMajority against majorityEnforceUpgrade.
* @param {Number} version
@ -324,6 +354,20 @@ ChainBlock.prototype.isUpgraded = function isUpgraded(version, ancestors) {
return this.isSuperMajority(version, network.block.majorityEnforceUpgrade, ancestors);
};
/**
* Check {@link ChainBlock#isUpgraded} asynchronously.
* @param {Number} version
* @param {Function} callback
* @returns {Boolean}
*/
ChainBlock.prototype.isUpgradedAsync = function isUpgradedAsync(version, callback) {
return this.isSuperMajorityAsync(
version,
network.block.majorityEnforceUpgrade,
callback);
};
/**
* Calculate found number of block versions within the majority window.
* @param {Number} version
@ -351,18 +395,21 @@ ChainBlock.prototype.isSuperMajority = function isSuperMajority(version, require
};
/**
* Get median time past asynchronously.
* @param {Function} callback - Returns [Error, Number].
* Calculate {@link ChainBlock#isSuperMajority asynchronously}.
* @param {Number} version
* @param {Number} required
* @param {Function} callback - Returns [Error, Boolean].
* @returns {Boolean}
*/
ChainBlock.prototype.getMedianTimeAsync = function getMedianTimeAsync(callback) {
ChainBlock.prototype.isSuperMajorityAsync = function isSuperMajorityAsync(version, required, callback) {
var self = this;
return this.getAncestors(constants.block.MEDIAN_TIMESPAN, function(err, ancestors) {
return this.getAncestors(network.block.majorityWindow, function(err, ancestors) {
if (err)
return callback(err);
return callback(null, self.getMedianTime(ancestors));
return callback(null, self.isSuperMajority(version, required, ancestors));
});
};

View File

@ -9,6 +9,7 @@ module.exports = function(bcoin) {
var utils = require('./utils');
var assert = utils.assert;
var network = bcoin.protocol.network;
/**
* Create a fullnode complete with a chain,
@ -47,9 +48,6 @@ function Fullnode(options) {
if (!(this instanceof Fullnode))
return new Fullnode(options);
if (!options)
options = {};
bcoin.node.call(this, options);
this.loaded = false;
@ -86,7 +84,7 @@ Fullnode.prototype._init = function _init() {
this.pool = new bcoin.pool({
chain: this.chain,
mempool: this.mempool,
witness: this.network.witness,
witness: network.witness,
listen: this.options.listen,
selfish: this.options.selfish,
spv: false

View File

@ -89,63 +89,6 @@ function Mempool(options) {
utils.inherits(Mempool, EventEmitter);
/**
* Standard verify flags.
* @const {VerifyFlags}
* @default
*/
Mempool.flags = constants.flags.STANDARD_VERIFY_FLAGS;
/**
* Mandatory verify flags.
* @const {VerifyFlags}
* @default
*/
Mempool.mandatory = constants.flags.MANDATORY_VERIFY_FLAGS;
/**
* Locktime flags.
* @const {LockFlags}
* @default
*/
Mempool.lockFlags = constants.flags.STANDARD_LOCKTIME_FLAGS;
/**
* Ancestor limit.
* @const {Number}
* @default
*/
Mempool.ANCESTOR_LIMIT = 25;
/**
* Maximum mempool size in bytes.
* @const {Number}
* @default
*/
Mempool.MAX_MEMPOOL_SIZE = 300 << 20;
/**
* The time at which transactions
* fall out of the mempool.
* @const {Number}
* @default
*/
Mempool.MEMPOOL_EXPIRY = 72 * 60 * 60;
/**
* Maximum number of orphan transactions.
* @const {Number}
* @default
*/
Mempool.MAX_ORPHAN_TX = 100;
Mempool.prototype._lock = function _lock(func, args, force) {
return this.locker.lock(func, args, force);
};
@ -340,12 +283,12 @@ Mempool.prototype.removeBlock = function removeBlock(block, callback, force) {
Mempool.prototype.limitMempoolSize = function limitMempoolSize(callback) {
var self = this;
if (this.size <= Mempool.MAX_MEMPOOL_SIZE)
if (this.size <= constants.mempool.MAX_MEMPOOL_SIZE)
return callback(null, true);
this.tx.getRange({
start: 0,
end: utils.now() - Mempool.MEMPOOL_EXPIRY
end: utils.now() - constants.mempool.MEMPOOL_EXPIRY
}, function(err, txs) {
if (err)
return callback(err);
@ -360,7 +303,7 @@ Mempool.prototype.limitMempoolSize = function limitMempoolSize(callback) {
if (err)
return callback(err);
return callback(self.size <= Mempool.MAX_MEMPOOL_SIZE);
return callback(self.size <= constants.mempool.MAX_MEMPOOL_SIZE);
});
});
});
@ -526,8 +469,8 @@ Mempool.prototype.hasTX = function hasTX(hash, callback) {
Mempool.prototype.addTX = function addTX(tx, callback, force) {
var self = this;
var flags = Mempool.flags;
var lockFlags = Mempool.lockFlags;
var flags = constants.flags.STANDARD_VERIFY_FLAGS;
var lockFlags = constants.flags.STANDARD_LOCKTIME_FLAGS;
var ret = {};
var now;
@ -561,6 +504,18 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) {
if (tx.isCoinbase())
return callback(new VerifyError(tx, 'invalid', 'coinbase', 100));
if (this.requireStandard) {
if (!tx.isStandard(flags, ret))
return callback(new VerifyError(tx, ret.reason, 0));
if (!this.chain.csvActive && tx.version >= 2) {
return callback(new VerifyError(tx,
'nonstandard',
'premature-version2-tx',
0));
}
}
this.chain.checkFinal(this.chain.tip, tx, lockFlags, function(err, isFinal) {
if (err)
return callback(err);
@ -568,11 +523,6 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) {
if (!isFinal)
return callback(new VerifyError(tx, 'nonstandard', 'non-final', 0));
if (self.requireStandard) {
if (!tx.isStandard(flags, ret))
return callback(new VerifyError(tx, ret.reason, 0));
}
self.seenTX(tx, function(err, exists) {
if (err)
return callback(err);
@ -600,7 +550,7 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) {
return callback(err);
if (!tx.hasCoins()) {
if (self.totalSize > Mempool.MAX_MEMPOOL_SIZE) {
if (self.totalSize > constants.mempool.MAX_MEMPOOL_SIZE) {
return callback(new VerifyError(tx,
'insufficientfee',
'mempool full',
@ -723,9 +673,9 @@ Mempool.prototype.removeUnchecked = function removeUnchecked(tx, callback) {
Mempool.prototype.verify = function verify(tx, callback) {
var self = this;
var height = this.chain.height + 1;
var lockFlags = Mempool.lockFlags;
var flags = Mempool.flags;
var mandatory = Mempool.mandatory;
var lockFlags = constants.flags.STANDARD_LOCKTIME_FLAGS;
var flags = constants.flags.STANDARD_VERIFY_FLAGS;
var mandatory = constants.flags.MANDATORY_VERIFY_FLAGS;
var ret = {};
var fee, now, free, minFee;
@ -808,7 +758,7 @@ Mempool.prototype.verify = function verify(tx, callback) {
if (err)
return callback(err);
if (count > Mempool.ANCESTOR_LIMIT) {
if (count > constants.mempool.ANCESTOR_LIMIT) {
return callback(new VerifyError(tx,
'nonstandard',
'too-long-mempool-chain',
@ -934,7 +884,7 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx, callback, force) {
batch.put('m/D/' + hash, tx.toExtended(true));
if (self.orphans > Mempool.MAX_ORPHAN_TX) {
if (self.orphans > constants.mempool.MAX_ORPHAN_TX) {
return self.purgeOrphans(function(err) {
if (err)
return callback(err);

View File

@ -8,7 +8,6 @@
module.exports = function(bcoin) {
var EventEmitter = require('events').EventEmitter;
var network = bcoin.protocol.network;
var utils = require('./utils');
/**
@ -31,7 +30,6 @@ function Node(options) {
this.options = options;
this.network = network;
this.mempool = null;
this.pool = null;
this.chain = null;

View File

@ -645,10 +645,12 @@ Peer.prototype._emitMerkle = function _emitMerkle() {
};
Peer.prototype._handleFilterLoad = function _handleFilterLoad(payload) {
var size = payload.filter.length * 8;
this.filter = new bcoin.bloom(size, payload.n, payload.tweak);
this.filter.filter = payload.filter;
this.filter.update = payload.update;
this.filter = new bcoin.bloom(
payload.filter,
payload.n,
payload.tweak,
payload.update
);
this.relay = true;
};

View File

@ -314,7 +314,6 @@ exports.hashTypeByVal = utils.revMap(exports.hashType);
exports.block = {
MAX_SIZE: 1000000,
MAX_SIGOPS: 1000000 / 50,
MAX_ORPHAN_TX: 1000000 / 100,
MEDIAN_TIMESPAN: 11,
BIP16_TIME: 1333238400,
SIGHASH_LIMIT: 1300000000
@ -355,6 +354,41 @@ exports.script = {
MAX_OP_RETURN: 80
};
exports.mempool = {};
/**
* Ancestor limit.
* @const {Number}
* @default
*/
exports.mempool.ANCESTOR_LIMIT = 25;
/**
* Maximum mempool size in bytes.
* @const {Number}
* @default
*/
exports.mempool.MAX_MEMPOOL_SIZE = 300 << 20;
/**
* The time at which transactions
* fall out of the mempool.
* @const {Number}
* @default
*/
exports.mempool.MEMPOOL_EXPIRY = 72 * 60 * 60;
/**
* Maximum number of orphan transactions.
* @const {Number}
* @default
*/
exports.mempool.MAX_ORPHAN_TX = 100;
/**
* Reject codes. Note that `internal` and higher
* are not meant for use on the p2p network.

View File

@ -9,6 +9,7 @@ module.exports = function(bcoin) {
var utils = require('./utils');
var assert = utils.assert;
var network = bcoin.protocol.network;
/**
* Create an spv node which only maintains
@ -36,9 +37,6 @@ function SPVNode(options) {
if (!(this instanceof SPVNode))
return new SPVNode(options);
if (!options)
options = {};
bcoin.node.call(this, options);
this.loaded = false;
@ -62,7 +60,7 @@ SPVNode.prototype._init = function _init() {
this.pool = new bcoin.pool({
chain: this.chain,
witness: this.network.witness,
witness: network.witness,
selfish: true,
listen: false,
spv: true