bloom/net: move bloom constants. net services, move inv types.

This commit is contained in:
Christopher Jeffrey 2017-01-06 01:51:40 -08:00
parent 3da4542ecb
commit d1a4e53896
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
12 changed files with 148 additions and 628 deletions

View File

@ -556,7 +556,7 @@ ChainEntry.prototype.toHeaders = function toHeaders() {
*/
ChainEntry.prototype.toInv = function toInv() {
return new InvItem(constants.inv.BLOCK, this.hash);
return new InvItem(InvItem.types.BLOCK, this.hash);
};
/**

View File

@ -2255,13 +2255,7 @@ FilterLoadPacket.fromRaw = function fromRaw(data, enc) {
*/
FilterLoadPacket.prototype.isWithinConstraints = function isWithinConstraints() {
if (this.filter.size > constants.bloom.MAX_BLOOM_FILTER_SIZE * 8)
return false;
if (this.filter.n > constants.bloom.MAX_HASH_FUNCS)
return false;
return true;
return this.filter.isWithinConstraints();
};
/**

View File

@ -25,7 +25,7 @@ var Block = require('../primitives/block');
var TX = require('../primitives/tx');
var errors = require('../btc/errors');
var NetAddress = require('../primitives/netaddress');
var invTypes = constants.inv;
var invTypes = InvItem.types;
var packetTypes = packets.types;
var VerifyResult = errors.VerifyResult;
@ -144,7 +144,7 @@ function Peer(pool) {
this.bip151,
this.hostname,
this.outbound,
this.pool.auth,
this.pool.authdb,
this.pool.identityKey);
this.bip151.bip150 = this.bip150;
}

View File

@ -28,7 +28,7 @@ var List = require('../utils/list');
var tcp = require('./tcp');
var dns = require('./dns');
var HostList = require('./hostlist');
var invTypes = constants.inv;
var invTypes = InvItem.types;
var VerifyError = errors.VerifyError;
var VerifyResult = errors.VerifyResult;
@ -108,7 +108,7 @@ function Pool(options) {
this.createServer = tcp.createServer;
this.resolve = dns.resolve;
this.locker = new Locker();
this.auth = null;
this.authdb = null;
this.identityKey = null;
this.proxyServer = null;
this.banTime = constants.BAN_TIME;
@ -116,8 +116,8 @@ function Pool(options) {
this.feeRate = -1;
// Required services.
this.needed = constants.services.NETWORK;
this.needed |= constants.services.WITNESS;
this.reqServices = constants.services.NETWORK;
this.reqServices |= constants.services.WITNESS;
this.syncing = false;
@ -166,7 +166,7 @@ Pool.prototype._initOptions = function _initOptions() {
if (!this.options.witness) {
this.address.services &= ~constants.services.WITNESS;
this.needed &= ~constants.services.WITNESS;
this.reqServices &= ~constants.services.WITNESS;
}
if (this.options.host != null) {
@ -209,16 +209,26 @@ Pool.prototype._initOptions = function _initOptions() {
this.proxyServer = this.options.proxyServer;
}
if (this.options.selfish) {
assert(typeof this.options.selfish === 'boolean');
this.address.services &= ~constants.services.NETWORK;
}
if (this.options.spv) {
assert(typeof this.options.spv === 'boolean');
this.address.services &= ~constants.services.NETWORK;
}
if (this.options.bip150) {
assert(typeof this.options.bip151 === 'boolean');
this.auth = new BIP150.AuthDB();
this.authdb = new BIP150.AuthDB();
if (this.options.authPeers)
this.auth.setAuthorized(this.options.authPeers);
this.authdb.setAuthorized(this.options.authPeers);
if (this.options.knownPeers)
this.auth.setKnown(this.options.knownPeers);
this.authdb.setKnown(this.options.knownPeers);
this.identityKey = this.options.identityKey || ec.generatePrivateKey();
@ -249,8 +259,8 @@ Pool.prototype._initOptions = function _initOptions() {
this.hosts.setSeeds([this.options.preferredSeed]);
if (this.options.spv) {
this.spvFilter = Bloom.fromRate(10000, 0.001, constants.bloom.ALL);
this.needed |= constants.services.BLOOM;
this.spvFilter = Bloom.fromRate(10000, 0.001, Bloom.flags.ALL);
this.reqServices |= constants.services.BLOOM;
}
if (!this.options.mempool)
@ -911,7 +921,7 @@ Pool.prototype.handleAddr = function handleAddr(peer, addrs) {
if (!addr.isRoutable())
continue;
if (!addr.hasServices(this.needed))
if (!addr.hasServices(this.reqServices))
continue;
if (this.hosts.add(addr, peer.address))
@ -1402,7 +1412,7 @@ Pool.prototype.getHost = function getHost(unique) {
if (!addr.isValid())
continue;
if (!addr.hasServices(this.needed))
if (!addr.hasServices(this.reqServices))
continue;
if (now - entry.lastAttempt < 600 && i < 30)

View File

@ -330,7 +330,7 @@ AbstractBlock.prototype.rhash = function() {
*/
AbstractBlock.prototype.toInv = function toInv() {
return new InvItem(constants.inv.BLOCK, this.hash('hex'));
return new InvItem(InvItem.types.BLOCK, this.hash('hex'));
};
/*

View File

@ -28,6 +28,38 @@ function InvItem(type, hash) {
this.hash = hash;
}
/**
* Inv types.
* @enum {Number}
* @default
*/
InvItem.types = {
ERROR: 0,
TX: 1,
BLOCK: 2,
FILTERED_BLOCK: 3,
WITNESS_TX: 1 | (1 << 30),
WITNESS_BLOCK: 2 | (1 << 30),
WITNESS_FILTERED_BLOCK: 3 | (1 << 30),
CMPCT_BLOCK: 4
};
/**
* Inv types by value.
* @const {RevMap}
*/
InvItem.typesByVal = util.revMap(InvItem.types);
/**
* Witness mask for inv types.
* @const {Number}
* @default
*/
InvItem.WITNESS_MASK = 1 << 30;
/**
* Write inv item to buffer writer.
* @param {BufferWriter} bw
@ -108,11 +140,11 @@ InvItem.fromRaw = function fromRaw(data, enc) {
InvItem.prototype.isBlock = function isBlock() {
switch (this.type) {
case constants.inv.BLOCK:
case constants.inv.WITNESS_BLOCK:
case constants.inv.FILTERED_BLOCK:
case constants.inv.WITNESS_FILTERED_BLOCK:
case constants.inv.CMPCT_BLOCK:
case InvItem.types.BLOCK:
case InvItem.types.WITNESS_BLOCK:
case InvItem.types.FILTERED_BLOCK:
case InvItem.types.WITNESS_FILTERED_BLOCK:
case InvItem.types.CMPCT_BLOCK:
return true;
default:
return false;
@ -126,8 +158,8 @@ InvItem.prototype.isBlock = function isBlock() {
InvItem.prototype.isTX = function isTX() {
switch (this.type) {
case constants.inv.TX:
case constants.inv.WITNESS_TX:
case InvItem.types.TX:
case InvItem.types.WITNESS_TX:
return true;
default:
return false;
@ -140,7 +172,7 @@ InvItem.prototype.isTX = function isTX() {
*/
InvItem.prototype.hasWitness = function hasWitness() {
return (this.type & constants.WITNESS_MASK) !== 0;
return (this.type & InvItem.WITNESS_MASK) !== 0;
};
/**

View File

@ -25,6 +25,7 @@ var Output = require('./output');
var Outpoint = require('./outpoint');
var InvItem = require('./invitem');
var workerPool = require('../workers/workerpool').pool;
var Bloom = require('../utils/bloom');
/*
* Constants
@ -1935,10 +1936,10 @@ TX.prototype.isWatched = function isWatched(filter) {
output = this.outputs[i];
// Test the output script
if (output.script.test(filter)) {
if (filter.update === constants.filterFlags.ALL) {
if (filter.update === Bloom.flags.ALL) {
prevout = Outpoint.fromTX(this, i);
filter.add(prevout.toRaw());
} else if (filter.update === constants.filterFlags.PUBKEY_ONLY) {
} else if (filter.update === Bloom.flags.PUBKEY_ONLY) {
if (output.script.isPubkey() || output.script.isMultisig()) {
prevout = Outpoint.fromTX(this, i);
filter.add(prevout.toRaw());
@ -2016,7 +2017,7 @@ TX.prototype.wtxid = function() {
*/
TX.prototype.toInv = function toInv() {
return new InvItem(constants.inv.TX, this.hash('hex'));
return new InvItem(InvItem.types.TX, this.hash('hex'));
};
/**

View File

@ -81,83 +81,6 @@ exports.LOCAL_SERVICES = 0
| exports.services.BLOOM
| exports.services.WITNESS;
/**
* Inv types.
* @enum {Number}
* @default
*/
exports.inv = {
ERROR: 0,
TX: 1,
BLOCK: 2,
FILTERED_BLOCK: 3,
WITNESS_TX: 1 | (1 << 30),
WITNESS_BLOCK: 2 | (1 << 30),
WITNESS_FILTERED_BLOCK: 3 | (1 << 30),
CMPCT_BLOCK: 4
};
/**
* Inv types by value.
* @const {RevMap}
*/
exports.invByVal = util.revMap(exports.inv);
/**
* Witness mask for inv types.
* @const {Number}
* @default
*/
exports.WITNESS_MASK = 1 << 30;
/**
* Bloom filter update flags.
* @enum {Number}
* @default
*/
exports.filterFlags = {
/**
* Never update the filter with outpoints.
*/
NONE: 0,
/**
* Always update the filter with outpoints.
*/
ALL: 1,
/**
* Only update the filter with outpoints if it is
* "asymmetric" in terms of addresses (pubkey/multisig).
*/
PUBKEY_ONLY: 2
};
/**
* Bloom filter limits.
* @enum {Number}
* @default
*/
exports.bloom = {
MAX_BLOOM_FILTER_SIZE: 36000,
MAX_HASH_FUNCS: 50
};
/**
* Bloom filter update flags by value.
* @const {RevMap}
*/
exports.filterFlagsByVal = util.revMap(exports.filterFlags);
/**
* Script opcodes.
* @enum {Number}

View File

@ -1,509 +0,0 @@
/**
* An inverse enum. Retrieves key by value.
* @typedef {Object} RevMap
* @global
*/
/**
* @typedef {Object} Path
* @property {String} name - Account name.
* @property {Number} account - Account index.
* @property {Number} change - Change chain.
* @property {Number} index - Address index.
* @global
*/
/**
* One of {@link module:constants.inv}.
* @typedef {Number|String} InvType
* @global
*/
/**
* @typedef {Object} Outpoint
* @property {Hash} hash
* @property {Number} index
* @global
*/
/**
* An output script type.
* @see {module:constants.scriptTypes}
* May sometimes be a string if specified.
* @typedef {Number|String} ScriptType
* @global
*/
/**
* A subset of {@link ScriptType}, including
* pubkeyhash, scripthash, witnesspubkeyhash,
* and witnessscripthash. This value
* specifically refers to the address prefix.
* It is a network-agnostic way of representing
* prefixes. May sometimes be a string if
* specified.
* @typedef {Number|String} AddressType
* @global
*/
/**
* A bitfield containing locktime flags.
* @typedef {Number} LockFlags
* @global
*/
/**
* A map of address hashes ({@link Hash} -> value).
* @typedef {Object} AddressMap
* @global
*/
/**
* @typedef {Object} ParsedURI
* @property {Base58Address} address
* @property {Amount?} amount? - Amount in satoshis.
* @property {String?} label
* @property {String?} message
* @property {String?} request - Payment request URL.
* @global
*/
/**
* Wallet ID
* @typedef {String} WalletID
* @global
*/
/**
* Base58 string.
* @typedef {String} Base58String
* @global
*/
/**
* Base58 address.
* @typedef {String} Base58Address
* @global
*/
/**
* Buffer or hex-string hash.
* @typedef {Buffer|String} Hash
* @global
*/
/**
* Reversed hex-string hash (uint256le).
* @typedef {String} ReversedHash
* @global
*/
/**
* Signature hash type. One of `all`, `single`, `none`, or
* one of {@link constants.hashType}.
* @typedef {String|Number} SighashType
* @global
*/
/**
* Wallet balance.
* @typedef {Object} Balance
* @property {Amount} confirmed
* @property {Amount} unconfirmed
* @property {Amount} total
* @global
*/
/**
* A satoshi amount. This is technically a
* JS double float, but it is regularly
* enforced to be less than 53 bits and
* less than MAX_MONEY in various
* functions.
* @typedef {Number} Amount
* @global
*/
/**
* Rate of satoshis per kB.
* @typedef {Amount} Rate
* @global
*/
/**
* A big number (bn.js)
* @typedef {Object} BN
* @global
*/
/**
* A bitfield containing script verify flags.
* @typedef {Number} VerifyFlags
* @global
*/
/**
* @typedef {Object} Orphan
* @property {Hash} hash - Orphan TX hash.
* @property {Number} index - Orphan input index.
* @global
*/
/**
* @typedef {Object} CoinSelection
* @property {Coin[]?} chosen - Selected coins.
* @property {Amount} change - Amount of change to add.
* @property {Amount} fee - Estimated fee.
* @property {Amount} total - Total value.
* @global
*/
/**
* @typedef {Object} DeploymentState
* @property {VerifyFlags} flags
* @property {LockFlags} lockFlags
* @property {Boolean} coinbaseHeight - Whether coinbase height is enforced.
* @property {Boolean} segwit
* @property {Boolean} csv
* @global
*/
/**
* @typedef {Object} SubmitOrderPacket
* @property {Hash} hash
* @property {TX} tx
* @global
*/
/**
* @typedef {Object} ReplyPacket
* @property {Hash} hash
* @property {Number} code
* @property {Buffer} publicKey
* @global
*/
/**
* @typedef {Object} FilterLoadPacket
* @see Bloom
* @property {Buffer} filter - Serialized bloom filter.
* @property {Number} n - Number of hash functions.
* @property {Number} tweak - Bloom filter seed.
* @property {String|Number} update (See {@link constants.filterFlags}).
* @global
*/
/**
* @typedef {Object} FilterAddPacket
* @see Bloom
* @property {Buffer} data - Data to add to filter.
* @global
*/
/**
* @typedef {Object} GetUTXOsPacket
* @property {Boolean} mempool - Check mempool.
* @property {Outpoint[]} prevout - Outpoints.
* @global
*/
/**
* @typedef {Object} NakedCoin
* @property {Number} version - Transaction version.
* @property {Number} height - Transaction height (-1 if unconfirmed).
* @property {Amount} value - Output value in satoshis.
* @property {Script} script - Output script.
* @property {Boolean} coinbase - Whether the containing
* transaction is a coinbase.
* @property {Hash} hash - Transaction hash.
* @property {Number} index - Output index.
* @global
*/
/**
* @typedef {Object} UTXOsPacket
* @property {Array?} data.hits - Hits (array of
* 1s and 0s representing a bit mask).
* @property {Buffer?} data.map - Hit map.
* @property {Object} data.height - Chain height.
* @property {Hash} data.tip - Chain tip hash.
* @property {Coin[]} data.coins
* @global
*/
/**
* @typedef {Object} PingPacket
* @property {BN} nonce
* @global
*/
/**
* @typedef {Object} NakedBlock
* @property {Number} version - Transaction version. Note that BCoin reads
* versions as unsigned even though they are signed at the protocol level.
* This value will never be negative.
* @property {Hash} prevBlock
* @property {Hash} merkleRoot
* @property {Number} ts
* @property {Number} bits
* @property {Number} nonce
* @property {Number} height
* @property {Number} totalTX
* @property {NakedTX[]?} txs - Only present on blocks.
* @property {Hash[]?} hashes - Only present on merkleblocks.
* @property {Buffer?} flags - Only present on merkleblocks.
* @property {Number?} coinbaseHeight - Only present on compactblocks.
* @global
*/
/**
* @typedef {Object} NakedInput
* @property {Outpoint} prevout
* @property {NakedScript} script - Input script.
* @property {Number} sequence - nSequence.
* @property {NakedWitness} witness - Witness.
* @global
*/
/**
* @typedef {Object} NakedOutput
* @property {Amount} value - Value in satoshis.
* @property {NakedScript} script - Output script.
* @global
*/
/**
* @typedef {Object} NakedCoin
* @property {Number} version - Transaction version.
* @property {Number} height - Transaction height (-1 if unconfirmed).
* @property {Amount} value - Output value in satoshis.
* @property {Script} script - Output script.
* @property {Boolean} coinbase - Whether the containing
* transaction is a coinbase.
* @property {Hash} hash - Transaction hash.
* @property {Number} index - Output index.
* @global
*/
/**
* @typedef {Object} NakedTX
* @property {Number} version
* @property {Number} flag
* @property {NakedInput[]} inputs
* @property {NakedOutput[]} outputs
* @property {Number} locktime
* @global
*/
/**
* @typedef {Object} NakedScript
* @property {Buffer} raw - Raw code.
* @property {Array} code - Parsed code.
* @global
*/
/**
* @typedef {Object} NakedWitness
* @property {Buffer[]} items - Stack items.
* @global
*/
/**
* @typedef {Object} FeeFilterPacket
* @property {Rate} rate
* @global
*/
/**
* One of `main`, `testnet`, `regtest`, `segnet3`, `segnet4`.
* @typedef {String} NetworkType
* @see {module:network.types}
* @global
*/
/*
* Callbacks & Events
*/
/**
* @callback TXCallback
* @param {Error?} err
* @param {TX} tx
* @global
*/
/**
* @callback TXSCallback
* @param {Error?} err
* @param {TX[]} txs
* @global
*/
/**
* @callback MTXCallback
* @param {Error?} err
* @param {MTX} tx
* @global
*/
/**
* @callback MTXSCallback
* @param {Error?} err
* @param {MTX[]} txs
* @global
*/
/**
* @callback CoinCallback
* @param {Error?} err
* @param {Coin} tx
* @global
*/
/**
* @callback CoinsCallback
* @param {Error?} err
* @param {Coin[]} tx
* @global
*/
/**
* @callback VerifyCallback
* @param {VerifyError?} err
* @global
*/
/**
* @callback BlockCallback
* @param {Error?} err
* @param {Block} block
* @global
*/
/**
* @callback EntryCallback
* @param {Error?} err
* @param {ChainEntry} entry
* @global
*/
/**
* @callback EntriesCallback
* @param {Error?} err
* @param {ChainEntry[]} entry
* @global
*/
/**
* @callback BalanceCallback
* @param {Error?} err
* @param {Balance} balance
* @global
*/
/**
* @callback BooleanCallback
* @param {Error?} err
* @param {Boolean} result
* @global
*/
/**
* @callback NumberCallback
* @param {Error?} err
* @param {Number} result
* @global
*/
/**
* @callback HashCallback
* @param {Error?} err
* @param {Hash} hash
* @global
*/
/**
* @callback HashesCallback
* @param {Error?} err
* @param {Hash[]} hash
* @global
*/
/**
* @callback WalletCallback
* @param {Error?} err
* @param {Wallet|NakedWallet} wallet
* @global
*/
/**
* @callback BufferCallback
* @param {Error?} err
* @param {Buffer} data
* @global
*/
/**
* @callback ObjectCallback
* @param {Error?} err
* @param {Object} obj
* @global
*/
/**
* @callback DeploymentCallback
* @param {(Error|VerifyError)?} err
* @param {DeploymentState} state
* @global
*/
/**
* @callback MinerBlockCallback
* @param {Error?} err
* @param {MinerBlock} block
* @global
*/
/**
* @callback AddressMapCallback
* @param {Error?} err
* @param {AddressMap} map
* @global
*/
/**
* @callback AddressTableCallback
* @param {Error?} err
* @param {AddressTable} table
* @global
*/
/**
* @callback OrphanCallback
* @param {Error?} err
* @param {Orphan} orphan
* @global
*/
/**
* @callback TSHeightCallback
* @param {Error?} err
* @param {Number} ts
* @param {Number} height
* @global
*/
/**
* @callback ConfidenceCallback
* @param {Error?} err
* @param {Confidence} confidence
* @global
*/
/**
* @callback HashHeightCallback
* @param {Error?} err
* @param {Hash} hash
* @param {Number} height
* @global
*/

View File

@ -34,7 +34,7 @@ var LN2 = 0.6931471805599453094172321214581765680755001343602552;
* @property {Number} size
* @property {Number} n
* @property {Number} tweak
* @property {Number} update - Update flag (see {@link constants.filterFlags}).
* @property {Number} update - Update flag (see {@link Bloom.flags}).
*/
function Bloom(size, n, tweak, update) {
@ -54,16 +54,70 @@ function Bloom(size, n, tweak, update) {
tweak = (Math.random() * 0x100000000) >>> 0;
if (update == null || update === -1)
update = constants.filterFlags.NONE;
update = Bloom.flags.NONE;
if (typeof update === 'string')
update = constants.filterFlags[update.toUpperCase()];
update = Bloom.flags[update.toUpperCase()];
this.n = n;
this.tweak = tweak;
this.update = update;
}
/**
* Bloom filter update flags.
* @enum {Number}
* @default
*/
Bloom.flags = {
/**
* Never update the filter with outpoints.
*/
NONE: 0,
/**
* Always update the filter with outpoints.
*/
ALL: 1,
/**
* Only update the filter with outpoints if it is
* "asymmetric" in terms of addresses (pubkey/multisig).
*/
PUBKEY_ONLY: 2
};
/**
* Bloom filter update flags by value.
* @const {RevMap}
*/
Bloom.flagsByVal = {
0: 'NONE',
1: 'ALL',
2: 'PUBKEY_ONLY'
};
/**
* Max bloom filter size.
* @const {Number}
* @default
*/
Bloom.MAX_BLOOM_FILTER_SIZE = 36000;
/**
* Max number of hash functions.
* @const {Number}
* @default
*/
Bloom.MAX_HASH_FUNCS = 50;
/**
* Perform the mumur3 hash on data.
* @param {Buffer} val
@ -164,16 +218,31 @@ Bloom.fromRate = function fromRate(items, rate, update) {
size = (-1 / LN2SQUARED * items * Math.log(rate)) | 0;
if (update !== -1)
size = Math.min(size, constants.bloom.MAX_BLOOM_FILTER_SIZE * 8);
size = Math.min(size, Bloom.MAX_BLOOM_FILTER_SIZE * 8);
n = ((size / items * LN2) | 0) || 1;
if (update !== -1)
n = Math.min(n, constants.bloom.MAX_HASH_FUNCS);
n = Math.min(n, Bloom.MAX_HASH_FUNCS);
return new Bloom(size, n, -1, update);
};
/**
* Ensure the filter is within the size limits.
* @returns {Boolean}
*/
Bloom.prototype.isWithinConstraints = function isWithinConstraints() {
if (this.size > Bloom.MAX_BLOOM_FILTER_SIZE * 8)
return false;
if (this.n > Bloom.MAX_HASH_FUNCS)
return false;
return true;
};
/**
* Get serialization size.
* @returns {Number}
@ -217,7 +286,7 @@ Bloom.prototype.fromReader = function fromReader(br) {
this.n = br.readU32();
this.tweak = br.readU32();
this.update = br.readU8();
assert(constants.filterFlagsByVal[this.update] != null, 'Bad filter flag.');
assert(Bloom.flagsByVal[this.update] != null, 'Bad filter flag.');
return this;
};

View File

@ -135,7 +135,7 @@ describe('Block', function() {
it('should create a merkle block', function() {
var filter, item1, item2, mblock2;
filter = Bloom.fromRate(1000, 0.01, constants.filterFlags.NONE);
filter = Bloom.fromRate(1000, 0.01, Bloom.flags.NONE);
item1 = '8e7445bbb8abd4b3174d80fa4c409fea6b94d96b';
item2 = '047b00000078da0dca3b0ec2300c00d0ab4466ed10'

View File

@ -59,7 +59,7 @@ describe('Bloom', function() {
});
it('should serialize to the correct format', function() {
var filter = new Bloom(952, 6, 3624314491, constants.filterFlags.NONE);
var filter = new Bloom(952, 6, 3624314491, Bloom.flags.NONE);
var item1 = '8e7445bbb8abd4b3174d80fa4c409fea6b94d96b';
var item2 = '047b00000078da0dca3b0ec2300c00d0ab4466ed10'
+ 'e763272c6c9ca052972c69e3884a9022084215e2eef'