From aa05bb5df79d9a3af53060a4c0c066226f6e9e4c Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 29 Jun 2017 00:22:20 -0700 Subject: [PATCH] refactor: use es6 maps for everything. --- lib/blockchain/chain.js | 56 ++++----- lib/blockchain/chaindb.js | 26 ++-- lib/coins/coinview.js | 25 ++-- lib/coins/undocoins.js | 6 +- lib/http/base.js | 31 +++-- lib/http/rpc.js | 44 +++---- lib/http/server.js | 2 +- lib/mempool/fees.js | 5 +- lib/mempool/mempool.js | 243 +++++++++++++++++--------------------- lib/mining/miner.js | 18 ++- lib/net/bip152.js | 9 +- lib/net/hostlist.js | 164 ++++++++++--------------- lib/net/peer.js | 38 ++---- lib/net/pool.js | 133 +++++++++------------ lib/protocol/timedata.js | 6 +- lib/script/sigcache.js | 10 +- lib/utils/lru.js | 18 +-- lib/utils/map.js | 136 --------------------- lib/utils/mappedlock.js | 46 ++++---- lib/wallet/txdb.js | 15 +-- lib/wallet/walletdb.js | 20 ++-- lib/workers/workerpool.js | 22 ++-- test/block-test.js | 58 +++------ test/node-test.js | 4 +- 24 files changed, 403 insertions(+), 732 deletions(-) delete mode 100644 lib/utils/map.js diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 03022cf4..ce8da7bf 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -80,9 +80,8 @@ function Chain(options) { this.height = -1; this.synced = false; - this.orphanMap = {}; - this.orphanPrev = {}; - this.orphanCount = 0; + this.orphanMap = new Map(); + this.orphanPrev = new Map(); this.db = new ChainDB(this); } @@ -1488,7 +1487,7 @@ Chain.prototype.verifyCheckpoint = function verifyCheckpoint(prev, hash) { Chain.prototype.storeOrphan = function storeOrphan(block, flags, id) { var hash = block.hash('hex'); var height = block.getCoinbaseHeight(); - var orphan = this.orphanPrev[block.prevBlock]; + var orphan = this.orphanPrev.get(block.prevBlock); // The orphan chain forked. if (orphan) { @@ -1526,13 +1525,12 @@ Chain.prototype.addOrphan = function addOrphan(orphan) { var block = orphan.block; var hash = block.hash('hex'); - assert(!this.orphanMap[hash]); - assert(!this.orphanPrev[block.prevBlock]); - assert(this.orphanCount >= 0); + assert(!this.orphanMap.has(hash)); + assert(!this.orphanPrev.has(block.prevBlock)); + assert(this.orphanMap.size >= 0); - this.orphanMap[hash] = orphan; - this.orphanPrev[block.prevBlock] = orphan; - this.orphanCount += 1; + this.orphanMap.set(hash, orphan); + this.orphanPrev.set(block.prevBlock, orphan); return orphan; }; @@ -1548,13 +1546,12 @@ Chain.prototype.removeOrphan = function removeOrphan(orphan) { var block = orphan.block; var hash = block.hash('hex'); - assert(this.orphanMap[hash]); - assert(this.orphanPrev[block.prevBlock]); - assert(this.orphanCount > 0); + assert(this.orphanMap.has(hash)); + assert(this.orphanPrev.has(block.prevBlock)); + assert(this.orphanMap.size > 0); - delete this.orphanMap[hash]; - delete this.orphanPrev[block.prevBlock]; - this.orphanCount -= 1; + this.orphanMap.delete(hash); + this.orphanPrev.delete(block.prevBlock); return orphan; }; @@ -1567,7 +1564,7 @@ Chain.prototype.removeOrphan = function removeOrphan(orphan) { */ Chain.prototype.hasNextOrphan = function hasNextOrphan(hash) { - return this.orphanPrev[hash] != null; + return this.orphanPrev.has(hash); }; /** @@ -1578,7 +1575,7 @@ Chain.prototype.hasNextOrphan = function hasNextOrphan(hash) { */ Chain.prototype.resolveOrphan = function resolveOrphan(hash) { - var orphan = this.orphanPrev[hash]; + var orphan = this.orphanPrev.get(hash); if (!orphan) return; @@ -1591,14 +1588,13 @@ Chain.prototype.resolveOrphan = function resolveOrphan(hash) { */ Chain.prototype.purgeOrphans = function purgeOrphans() { - var count = this.orphanCount; + var count = this.orphanMap.size; if (count === 0) return; - this.orphanMap = {}; - this.orphanPrev = {}; - this.orphanCount = 0; + this.orphanMap.clear(); + this.orphanPrev.clear(); this.logger.debug('Purged %d orphans.', count); }; @@ -1610,13 +1606,9 @@ Chain.prototype.purgeOrphans = function purgeOrphans() { Chain.prototype.limitOrphans = function limitOrphans() { var now = util.now(); - var hashes = Object.keys(this.orphanMap); - var i, hash, orphan, oldest; - - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; - orphan = this.orphanMap[hash]; + var orphan, oldest; + for (orphan of this.orphanMap.values()) { if (now < orphan.ts + 60 * 60) { if (!oldest || orphan.ts < oldest.ts) oldest = orphan; @@ -1626,7 +1618,7 @@ Chain.prototype.limitOrphans = function limitOrphans() { this.removeOrphan(orphan); } - if (this.orphanCount < this.options.maxOrphans) + if (this.orphanMap.size < this.options.maxOrphans) return; if (!oldest) @@ -1724,7 +1716,7 @@ Chain.prototype.hasEntry = function hasEntry(hash) { */ Chain.prototype.getOrphan = function getOrphan(hash) { - return this.orphanMap[hash] || null; + return this.orphanMap.get(hash) || null; }; /** @@ -1734,7 +1726,7 @@ Chain.prototype.getOrphan = function getOrphan(hash) { */ Chain.prototype.hasOrphan = function hasOrphan(hash) { - return this.orphanMap[hash] != null; + return this.orphanMap.has(hash); }; /** @@ -1907,7 +1899,7 @@ Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) { assert(hash); for (;;) { - orphan = this.orphanMap[hash]; + orphan = this.orphanMap.get(hash); if (!orphan) break; diff --git a/lib/blockchain/chaindb.js b/lib/blockchain/chaindb.js index ffc64938..b86bd0a6 100644 --- a/lib/blockchain/chaindb.js +++ b/lib/blockchain/chaindb.js @@ -935,12 +935,9 @@ ChainDB.prototype.getCoinView = async function getCoinView(tx) { ChainDB.prototype.getSpentView = async function getSpentView(tx) { var view = await this.getCoinView(tx); - var entries = view.toArray(); - var i, coins, meta; - - for (i = 0; i < entries.length; i++) { - coins = entries[i]; + var coins, meta; + for (coins of view.map.values()) { if (!coins.isEmpty()) continue; @@ -1703,12 +1700,9 @@ ChainDB.prototype.removeBlock = async function removeBlock(entry) { */ ChainDB.prototype.saveView = function saveView(view) { - var i, coins, raw; + var coins, raw; - view = view.toArray(); - - for (i = 0; i < view.length; i++) { - coins = view[i]; + for (coins of view.map.values()) { if (coins.isEmpty()) { this.del(layout.c(coins.hash)); this.coinCache.unpush(coins.hash); @@ -2181,7 +2175,7 @@ StateCache.prototype._init = function _init() { for (i = 0; i < this.network.deploys.length; i++) { deployment = this.network.deploys[i]; assert(!this.bits[deployment.bit]); - this.bits[deployment.bit] = {}; + this.bits[deployment.bit] = new Map(); } }; @@ -2190,8 +2184,8 @@ StateCache.prototype.set = function set(bit, entry, state) { assert(cache); - if (cache[entry.hash] !== state) { - cache[entry.hash] = state; + if (cache.get(entry.hash) !== state) { + cache.set(entry.hash, state); this.updates.push(new CacheUpdate(bit, entry.hash, state)); } }; @@ -2202,7 +2196,7 @@ StateCache.prototype.get = function get(bit, entry) { assert(cache); - state = cache[entry.hash]; + state = cache.get(entry.hash); if (state == null) return -1; @@ -2221,7 +2215,7 @@ StateCache.prototype.drop = function drop() { update = this.updates[i]; cache = this.bits[update.bit]; assert(cache); - delete cache[update.hash]; + cache.delete(update.hash); } this.updates.length = 0; @@ -2230,7 +2224,7 @@ StateCache.prototype.drop = function drop() { StateCache.prototype.insert = function insert(bit, hash, state) { var cache = this.bits[bit]; assert(cache); - cache[hash] = state; + cache.set(hash, state); }; /** diff --git a/lib/coins/coinview.js b/lib/coins/coinview.js index 4c24deb7..439a5119 100644 --- a/lib/coins/coinview.js +++ b/lib/coins/coinview.js @@ -26,7 +26,7 @@ function CoinView() { if (!(this instanceof CoinView)) return new CoinView(); - this.map = {}; + this.map = new Map(); this.undo = new UndoCoins(); } @@ -37,7 +37,7 @@ function CoinView() { */ CoinView.prototype.get = function get(hash) { - return this.map[hash]; + return this.map.get(hash); }; /** @@ -47,7 +47,7 @@ CoinView.prototype.get = function get(hash) { */ CoinView.prototype.has = function has(hash) { - return this.map[hash] != null; + return this.map.has(hash); }; /** @@ -56,7 +56,7 @@ CoinView.prototype.has = function has(hash) { */ CoinView.prototype.add = function add(coins) { - this.map[coins.hash] = coins; + this.map.set(coins.hash, coins); return coins; }; @@ -67,10 +67,10 @@ CoinView.prototype.add = function add(coins) { */ CoinView.prototype.remove = function remove(hash) { - if (!this.map[hash]) + if (!this.map.has(hash)) return false; - delete this.map[hash]; + this.map.delete(hash); return true; }; @@ -304,7 +304,7 @@ CoinView.prototype.isCoinbase = function isCoinbase(input) { */ CoinView.prototype.readCoins = async function readCoins(db, hash) { - var coins = this.map[hash]; + var coins = this.map.get(hash); if (!coins) { coins = await db.getCoins(hash); @@ -312,7 +312,7 @@ CoinView.prototype.readCoins = async function readCoins(db, hash) { if (!coins) return; - this.map[hash] = coins; + this.map.set(hash, coins); } return coins; @@ -371,14 +371,11 @@ CoinView.prototype.spendInputs = async function spendInputs(db, tx) { */ CoinView.prototype.toArray = function toArray() { - var keys = Object.keys(this.map); var out = []; - var i, hash; + var coins; - for (i = 0; i < keys.length; i++) { - hash = keys[i]; - out.push(this.map[hash]); - } + for (coins of this.map.values()) + out.push(coins); return out; }; diff --git a/lib/coins/undocoins.js b/lib/coins/undocoins.js index 19ef2e19..15d3cc9e 100644 --- a/lib/coins/undocoins.js +++ b/lib/coins/undocoins.js @@ -158,15 +158,15 @@ UndoCoins.prototype.apply = function apply(view, outpoint) { if (undo.height !== -1) { coins = new Coins(); - assert(!view.map[hash]); - view.map[hash] = coins; + assert(!view.map.has(hash)); + view.map.set(hash, coins); coins.hash = hash; coins.coinbase = undo.coinbase; coins.height = undo.height; coins.version = undo.version; } else { - coins = view.map[hash]; + coins = view.map.get(hash); assert(coins); } diff --git a/lib/http/base.js b/lib/http/base.js index 9d394e50..6e14ae87 100644 --- a/lib/http/base.js +++ b/lib/http/base.js @@ -41,7 +41,7 @@ function HTTPBase(options) { this.server = null; this.io = null; this.sockets = new List(); - this.channels = {}; + this.channels = new Map(); this.routes = new Routes(); this.mounts = []; this.stack = []; @@ -552,7 +552,7 @@ HTTPBase.prototype._initSockets = function _initSockets() { */ HTTPBase.prototype.to = function to(name) { - var list = this.channels[name]; + var list = this.channels.get(name); var i, args, item, socket; if (!list) @@ -630,13 +630,10 @@ HTTPBase.prototype.addSocket = function addSocket(ws) { */ HTTPBase.prototype.removeSocket = function removeSocket(socket) { - var keys = Object.keys(socket.channels); - var i, key; + var key; - for (i = 0; i < keys.length; i++) { - key = keys[i]; + for (key of socket.channels.keys()) this.leaveChannel(socket, key); - } assert(this.sockets.remove(socket)); }; @@ -649,21 +646,21 @@ HTTPBase.prototype.removeSocket = function removeSocket(socket) { */ HTTPBase.prototype.joinChannel = function joinChannel(socket, name) { - var list = this.channels[name]; - var item = socket.channels[name]; + var list = this.channels.get(name); + var item = socket.channels.get(name); if (item) return; if (!list) { list = new List(); - this.channels[name] = list; + this.channels.set(name, list); } item = new ListItem(socket); list.push(item); - socket.channels[name] = item; + socket.channels.set(name, item); }; /** @@ -674,8 +671,8 @@ HTTPBase.prototype.joinChannel = function joinChannel(socket, name) { */ HTTPBase.prototype.leaveChannel = function leaveChannel(socket, name) { - var list = this.channels[name]; - var item = socket.channels[name]; + var list = this.channels.get(name); + var item = socket.channels.get(name); if (!item) return; @@ -684,9 +681,9 @@ HTTPBase.prototype.leaveChannel = function leaveChannel(socket, name) { assert(list.remove(item)); if (list.size === 0) - delete this.channels[name]; + this.channels.delete(name); - delete socket.channels[name]; + socket.channels.delete(name); }; /** @@ -696,7 +693,7 @@ HTTPBase.prototype.leaveChannel = function leaveChannel(socket, name) { */ HTTPBase.prototype.channel = function channel(name) { - var list = this.channels[name]; + var list = this.channels.get(name); if (!list) return; @@ -1558,7 +1555,7 @@ function WebSocket(socket, ctx) { this.socket = socket; this.remoteAddress = socket.conn.remoteAddress; this.hooks = {}; - this.channels = {}; + this.channels = new Map(); this.auth = false; this.filter = null; this.prev = null; diff --git a/lib/http/rpc.js b/lib/http/rpc.js index 594954e9..f32254be 100644 --- a/lib/http/rpc.js +++ b/lib/http/rpc.js @@ -67,7 +67,7 @@ function RPC(node) { this.boundChain = false; this.nonce1 = 0; this.nonce2 = 0; - this.merkleMap = {}; + this.merkleMap = new Map(); this.pollers = []; this.init(); @@ -225,16 +225,12 @@ RPC.prototype.stop = async function stop(args, help) { RPC.prototype.getNetworkInfo = async function getNetworkInfo(args, help) { var hosts = this.pool.hosts; var locals = []; - var i, keys, key, local; + var local; if (help || args.length !== 0) throw new RPCError(errs.MISC_ERROR, 'getnetworkinfo'); - keys = hosts.local.keys(); - - for (i = 0; i < keys.length; i++) { - key = keys[i]; - local = hosts.local.get(key); + for (local of hosts.local.values()) { locals.push({ address: local.addr.host, port: local.addr.port, @@ -398,7 +394,7 @@ RPC.prototype.getPeerInfo = async function getPeerInfo(args, help) { throw new RPCError(errs.MISC_ERROR, 'getpeerinfo'); for (peer = this.pool.peers.head(); peer; peer = peer.next) { - offset = this.network.time.known[peer.hostname()]; + offset = this.network.time.known.get(peer.hostname()); if (offset == null) offset = 0; @@ -475,17 +471,14 @@ RPC.prototype.setBan = async function setBan(args, help) { }; RPC.prototype.listBanned = async function listBanned(args, help) { - var i, banned, keys, host, time; + var banned, host, time; if (help || args.length !== 0) throw new RPCError(errs.MISC_ERROR, 'listbanned'); banned = []; - keys = Object.keys(this.pool.hosts.banned); - for (i = 0; i < keys.length; i++) { - host = keys[i]; - time = this.pool.hosts.banned[host]; + for ([host, time] of this.pool.hosts.banned) { banned.push({ address: host, banned_until: time + this.pool.options.banTime, @@ -704,7 +697,7 @@ RPC.prototype.getMempoolInfo = async function getMempoolInfo(args, help) { throw new RPCError(errs.MISC_ERROR, 'No mempool available.'); return { - size: this.mempool.totalTX, + size: this.mempool.map.size, bytes: this.mempool.getSize(), usage: this.mempool.getSize(), maxmempool: this.mempool.options.maxSize, @@ -814,7 +807,7 @@ RPC.prototype.getRawMempool = async function getRawMempool(args, help) { var valid = new Validator([args]); var verbose = valid.bool(0, false); var out = {}; - var i, hashes, hash, entry; + var entry, hashes; if (help || args.length > 1) throw new RPCError(errs.MISC_ERROR, 'getrawmempool ( verbose )'); @@ -823,17 +816,8 @@ RPC.prototype.getRawMempool = async function getRawMempool(args, help) { throw new RPCError(errs.MISC_ERROR, 'No mempool available.'); if (verbose) { - hashes = this.mempool.getSnapshot(); - - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; - entry = this.mempool.getEntry(hash); - - if (!entry) - continue; - + for (entry of this.mempool.map.values()) out[entry.txid()] = this.entryToJSON(entry); - } return out; } @@ -1075,7 +1059,7 @@ RPC.prototype._submitWork = async function _submitWork(data) { if (!header.verify()) return false; - nonces = this.merkleMap[header.merkleRoot]; + nonces = this.merkleMap.get(header.merkleRoot); if (!nonces) return false; @@ -2291,7 +2275,7 @@ RPC.prototype.refreshBlock = function refreshBlock() { this.attempt = null; this.lastActivity = 0; - this.merkleMap = {}; + this.merkleMap.clear(); this.nonce1 = 0; this.nonce2 = 0; this.pollers = []; @@ -2370,7 +2354,7 @@ RPC.prototype.updateWork = async function updateWork() { root = attempt.getRoot(n1, n2); root = root.toString('hex'); - this.merkleMap[root] = new Nonces(n1, n2); + this.merkleMap.set(root, new Nonces(n1, n2)); return attempt; } @@ -2390,7 +2374,7 @@ RPC.prototype.updateWork = async function updateWork() { this.attempt = attempt; this.lastActivity = util.now(); - this.merkleMap[root] = new Nonces(n1, n2); + this.merkleMap.set(root, new Nonces(n1, n2)); return attempt; }; @@ -2454,7 +2438,7 @@ RPC.prototype._addBlock = async function _addBlock(block) { }; RPC.prototype.totalTX = function totalTX() { - return this.mempool ? this.mempool.totalTX : 0; + return this.mempool ? this.mempool.map.size : 0; }; RPC.prototype.getSoftforks = function getSoftforks() { diff --git a/lib/http/server.js b/lib/http/server.js index 68b85b43..309f2854 100644 --- a/lib/http/server.js +++ b/lib/http/server.js @@ -104,7 +104,7 @@ HTTPServer.prototype.initRouter = function initRouter() { this.use(this.jsonRPC(this.rpc)); this.get('/', async function(req, res) { - var totalTX = this.mempool ? this.mempool.totalTX : 0; + var totalTX = this.mempool ? this.mempool.map.size : 0; var size = this.mempool ? this.mempool.getSize() : 0; var addr = this.pool.hosts.getLocal(); diff --git a/lib/mempool/fees.js b/lib/mempool/fees.js index 06881e6c..82174aba 100644 --- a/lib/mempool/fees.js +++ b/lib/mempool/fees.js @@ -15,7 +15,6 @@ var policy = require('../protocol/policy'); var BufferReader = require('../utils/reader'); var StaticWriter = require('../utils/staticwriter'); var encoding = require('../utils/encoding'); -var Map = require('../utils/map'); var Logger = require('../node/logger'); /* @@ -490,7 +489,7 @@ PolicyEstimator.prototype.reset = function reset() { this.priUnlikely = 0; this.priLikely = INF_PRIORITY; - this.map.reset(); + this.map.clear(); this.bestHeight = 0; this.init(); @@ -511,7 +510,7 @@ PolicyEstimator.prototype.removeTX = function removeTX(hash) { this.feeStats.removeTX(item.blockHeight, this.bestHeight, item.bucketIndex); - this.map.remove(hash); + this.map.delete(hash); }; /** diff --git a/lib/mempool/mempool.js b/lib/mempool/mempool.js index eb00cd2e..bbceb34a 100644 --- a/lib/mempool/mempool.js +++ b/lib/mempool/mempool.js @@ -26,7 +26,6 @@ var encoding = require('../utils/encoding'); var layout = require('./layout'); var LDB = require('../db/ldb'); var Fees = require('./fees'); -var Map = require('../utils/map'); var CoinView = require('../coins/coinview'); var Coins = require('../coins/coins'); var Heap = require('../utils/heap'); @@ -51,7 +50,6 @@ var VerifyResult = errors.VerifyResult; * @property {Boolean} loaded * @property {Object} db * @property {Number} size - * @property {Number} totalOrphans * @property {Lock} locker * @property {Number} freeCount * @property {Number} lastTime @@ -82,17 +80,15 @@ function Mempool(options) { this.cache = new MempoolCache(this.options); this.size = 0; - this.totalOrphans = 0; - this.totalTX = 0; this.freeCount = 0; this.lastTime = 0; this.lastFlush = 0; this.tip = this.network.genesis.hash; - this.waiting = {}; - this.orphans = {}; - this.map = {}; - this.spents = {}; + this.waiting = new Map(); + this.orphans = new Map(); + this.map = new Map(); + this.spents = new Map(); this.rejects = new RollingFilter(120000, 0.000001); this.coinIndex = new CoinIndex(); @@ -196,7 +192,7 @@ Mempool.prototype.addBlock = async function addBlock(block, txs) { Mempool.prototype._addBlock = async function addBlock(block, txs) { var i, entries, entry, tx, hash; - if (this.totalTX === 0) { + if (this.map.size === 0) { this.tip = block.hash; return; } @@ -277,7 +273,7 @@ Mempool.prototype._removeBlock = async function removeBlock(block, txs) { var total = 0; var i, tx, hash; - if (this.totalTX === 0) { + if (this.map.size === 0) { this.tip = block.prevBlock; return; } @@ -337,16 +333,14 @@ Mempool.prototype.reset = async function reset() { */ Mempool.prototype._reset = async function reset() { - this.logger.info('Mempool reset (%d txs removed).', this.totalTX); + this.logger.info('Mempool reset (%d txs removed).', this.map.size); this.size = 0; - this.totalOrphans = 0; - this.totalTX = 0; - this.waiting = {}; - this.orphans = {}; - this.map = {}; - this.spents = {}; + this.waiting.clear(); + this.orphans.clear(); + this.map.clear(); + this.spents.clear(); this.coinIndex.reset(); this.txIndex.reset(); @@ -453,7 +447,7 @@ Mempool.prototype.limitSize = function limitSize(added) { */ Mempool.prototype.getTX = function getTX(hash) { - var entry = this.map[hash]; + var entry = this.map.get(hash); if (!entry) return; return entry.tx; @@ -466,7 +460,7 @@ Mempool.prototype.getTX = function getTX(hash) { */ Mempool.prototype.getEntry = function getEntry(hash) { - return this.map[hash]; + return this.map.get(hash); }; /** @@ -477,7 +471,7 @@ Mempool.prototype.getEntry = function getEntry(hash) { */ Mempool.prototype.getCoin = function getCoin(hash, index) { - var entry = this.map[hash]; + var entry = this.map.get(hash); if (!entry) return; @@ -503,7 +497,7 @@ Mempool.prototype.getCoin = function getCoin(hash, index) { Mempool.prototype.isSpent = function isSpent(hash, index) { var key = Outpoint.toKey(hash, index); - return this.spents[key] != null; + return this.spents.has(key); }; /** @@ -515,7 +509,7 @@ Mempool.prototype.isSpent = function isSpent(hash, index) { Mempool.prototype.getSpent = function getSpent(hash, index) { var key = Outpoint.toKey(hash, index); - return this.spents[key]; + return this.spents.get(key); }; /** @@ -527,7 +521,7 @@ Mempool.prototype.getSpent = function getSpent(hash, index) { Mempool.prototype.getSpentTX = function getSpentTX(hash, index) { var key = Outpoint.toKey(hash, index); - var entry = this.spents[key]; + var entry = this.spents.get(key); if (!entry) return; @@ -633,7 +627,7 @@ Mempool.prototype.getMeta = function getMeta(hash) { */ Mempool.prototype.hasEntry = function hasEntry(hash) { - return this.map[hash] != null; + return this.map.has(hash); }; /** @@ -1098,7 +1092,7 @@ Mempool.prototype.addEntry = async function addEntry(entry, view) { this.logger.debug( 'Added %s to mempool (txs=%d).', - tx.txid(), this.totalTX); + tx.txid(), this.map.size); this.cache.save(entry); @@ -1406,20 +1400,14 @@ Mempool.prototype.hasDepends = function hasDepends(tx) { */ Mempool.prototype.getBalance = function getBalance() { - var hashes = this.getSnapshot(); var total = 0; - var i, j, tx, hash, coin; + var i, hash, entry, tx, coin; - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; - tx = this.getTX(hash); + for ([hash, entry] of this.map) { + tx = entry.tx; - assert(tx); - - hash = tx.hash('hex'); - - for (j = 0; j < tx.outputs.length; j++) { - coin = this.getCoin(hash, j); + for (i = 0; i < tx.outputs.length; i++) { + coin = this.getCoin(hash, i); if (coin) total += coin.value; } @@ -1434,18 +1422,11 @@ Mempool.prototype.getBalance = function getBalance() { */ Mempool.prototype.getHistory = function getHistory() { - var hashes = this.getSnapshot(); var txs = []; - var i, hash, tx; + var entry; - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; - tx = this.getTX(hash); - - assert(tx); - - txs.push(tx); - } + for (entry of this.map.values()) + txs.push(entry.tx); return txs; }; @@ -1457,7 +1438,7 @@ Mempool.prototype.getHistory = function getHistory() { */ Mempool.prototype.getOrphan = function getOrphan(hash) { - return this.orphans[hash]; + return this.orphans.get(hash); }; /** @@ -1466,7 +1447,7 @@ Mempool.prototype.getOrphan = function getOrphan(hash) { */ Mempool.prototype.hasOrphan = function hasOrphan(hash) { - return this.orphans[hash] != null; + return this.orphans.has(hash); }; /** @@ -1504,14 +1485,13 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx, missing, id) { for (i = 0; i < missing.length; i++) { prev = missing[i]; - if (!this.waiting[prev]) - this.waiting[prev] = new Map(); + if (!this.waiting.has(prev)) + this.waiting.set(prev, new Set()); - this.waiting[prev].insert(hash); + this.waiting.get(prev).add(hash); } - this.orphans[hash] = new Orphan(tx, missing.length, id); - this.totalOrphans++; + this.orphans.set(hash, new Orphan(tx, missing.length, id)); this.logger.debug('Added orphan %s to mempool.', tx.txid()); @@ -1578,30 +1558,27 @@ Mempool.prototype.handleOrphans = async function handleOrphans(parent) { Mempool.prototype.resolveOrphans = function resolveOrphans(parent) { var hash = parent.hash('hex'); - var map = this.waiting[hash]; + var set = this.waiting.get(hash); var resolved = []; - var i, hashes, orphanHash, orphan; + var orphanHash, orphan; - if (!map) + if (!set) return resolved; - hashes = map.keys(); - assert(hashes.length > 0); + assert(set.size > 0); - for (i = 0; i < hashes.length; i++) { - orphanHash = hashes[i]; + for (orphanHash of set.keys()) { orphan = this.getOrphan(orphanHash); assert(orphan); if (--orphan.missing === 0) { - delete this.orphans[orphanHash]; - this.totalOrphans--; + this.orphans.delete(orphanHash); resolved.push(orphan); } } - delete this.waiting[hash]; + this.waiting.delete(hash); return resolved; }; @@ -1614,7 +1591,7 @@ Mempool.prototype.resolveOrphans = function resolveOrphans(parent) { Mempool.prototype.removeOrphan = function removeOrphan(hash) { var orphan = this.getOrphan(hash); - var i, tx, map, prevout, prev; + var i, tx, set, prevout, prev; if (!orphan) return false; @@ -1622,8 +1599,7 @@ Mempool.prototype.removeOrphan = function removeOrphan(hash) { try { tx = orphan.toTX(); } catch (e) { - delete this.orphans[hash]; - this.totalOrphans--; + this.orphans.delete(hash); this.logger.warning('%s %s', 'Warning: possible memory corruption.', 'Orphan failed deserialization.'); @@ -1634,21 +1610,20 @@ Mempool.prototype.removeOrphan = function removeOrphan(hash) { for (i = 0; i < prevout.length; i++) { prev = prevout[i]; - map = this.waiting[prev]; + set = this.waiting.get(prev); - if (!map) + if (!set) continue; - assert(map.has(hash)); + assert(set.has(hash)); - map.remove(hash); + set.delete(hash); - if (map.size === 0) - delete this.waiting[prev]; + if (set.size === 0) + this.waiting.delete(prev); } - delete this.orphans[hash]; - this.totalOrphans--; + this.orphans.delete(hash); this.emit('remove orphan', tx); @@ -1661,14 +1636,18 @@ Mempool.prototype.removeOrphan = function removeOrphan(hash) { */ Mempool.prototype.limitOrphans = function limitOrphans() { - var hashes = Object.keys(this.orphans); var index, hash; - if (this.totalOrphans < this.options.maxOrphans) + if (this.orphans.size < this.options.maxOrphans) return false; - index = random.randomRange(0, hashes.length); - hash = hashes[index]; + index = random.randomRange(0, this.orphans.size); + + for (hash of this.orphans.keys()) { + if (index === 0) + break; + index--; + } this.logger.debug('Removing orphan %s from mempool.', util.revHex(hash)); @@ -1785,7 +1764,13 @@ Mempool.prototype.findMissing = function findMissing(tx, view) { */ Mempool.prototype.getSnapshot = function getSnapshot() { - return Object.keys(this.map); + var keys = []; + var hash; + + for (hash of this.map.keys()) + keys.push(hash); + + return keys; }; /** @@ -1823,22 +1808,21 @@ Mempool.prototype.trackEntry = function trackEntry(entry, view) { var hash = tx.hash('hex'); var i, input, key; - assert(!this.map[hash]); - this.map[hash] = entry; + assert(!this.map.has(hash)); + this.map.set(hash, entry); assert(!tx.isCoinbase()); for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; key = input.prevout.toKey(); - this.spents[key] = entry; + this.spents.set(key, entry); } if (this.options.indexAddress && view) this.indexEntry(entry, view); this.size += entry.memUsage(); - this.totalTX++; }; /** @@ -1852,22 +1836,21 @@ Mempool.prototype.untrackEntry = function untrackEntry(entry) { var hash = tx.hash('hex'); var i, input, key; - assert(this.map[hash]); - delete this.map[hash]; + assert(this.map.has(hash)); + this.map.delete(hash); assert(!tx.isCoinbase()); for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; key = input.prevout.toKey(); - delete this.spents[key]; + this.spents.delete(key); } if (this.options.indexAddress) this.unindexEntry(entry); this.size -= entry.memUsage(); - this.totalTX--; }; /** @@ -2186,47 +2169,40 @@ MempoolOptions.fromOptions = function fromOptions(options) { function TXIndex() { // Map of addr->entries. - this.index = {}; + this.index = new Map(); // Map of txid->addrs. - this.map = {}; + this.map = new Map(); } TXIndex.prototype.reset = function reset() { - this.index = {}; - this.map = {}; + this.index.clear(); + this.map.clear(); }; TXIndex.prototype.get = function get(addr) { - var items = this.index[addr]; + var items = this.index.get(addr); var out = []; - var i, keys, entry; + var entry; if (!items) return out; - keys = items.keys(); - - for (i = 0; i < keys.length; i++) { - entry = items.get(keys[i]); + for (entry of items.values()) out.push(entry.tx); - } return out; }; TXIndex.prototype.getMeta = function getMeta(addr) { - var items = this.index[addr]; + var items = this.index.get(addr); var out = []; - var i, entry, keys, meta; + var entry, meta; if (!items) return out; - keys = items.keys(); - - for (i = 0; i < keys.length; i++) { - entry = items.get(keys[i]); + for (entry of items.values()) { meta = TXMeta.fromTX(entry.tx); meta.ps = entry.ts; out.push(meta); @@ -2239,48 +2215,46 @@ TXIndex.prototype.insert = function insert(entry, view) { var tx = entry.tx; var hash = tx.hash('hex'); var addrs = tx.getHashes(view, 'hex'); - var i, addr, items; + var addr, items; if (addrs.length === 0) return; - for (i = 0; i < addrs.length; i++) { - addr = addrs[i]; - items = this.index[addr]; + for (addr of addrs) { + items = this.index.get(addr); if (!items) { items = new Map(); - this.index[addr] = items; + this.index.set(addr, items); } assert(!items.has(hash)); items.set(hash, entry); } - this.map[hash] = addrs; + this.map.set(hash, addrs); }; TXIndex.prototype.remove = function remove(hash) { - var addrs = this.map[hash]; - var i, addr, items; + var addrs = this.map.get(hash); + var addr, items; if (!addrs) return; - for (i = 0; i < addrs.length; i++) { - addr = addrs[i]; - items = this.index[addr]; + for (addr of addrs) { + items = this.index.get(addr); assert(items); assert(items.has(hash)); - items.remove(hash); + items.delete(hash); if (items.size === 0) - delete this.index[addr]; + this.index.delete(addr); } - delete this.map[hash]; + this.map.delete(hash); }; /** @@ -2291,32 +2265,27 @@ TXIndex.prototype.remove = function remove(hash) { function CoinIndex() { // Map of addr->coins. - this.index = {}; + this.index = new Map(); // Map of outpoint->addr. - this.map = {}; + this.map = new Map(); } CoinIndex.prototype.reset = function reset() { - this.index = {}; - this.map = {}; + this.index.clear(); + this.map.clear(); }; CoinIndex.prototype.get = function get(addr) { - var items = this.index[addr]; + var items = this.index.get(addr); var out = []; - var i, keys, coin; + var coin; if (!items) return out; - keys = items.keys(); - - for (i = 0; i < keys.length; i++) { - coin = items.get(keys[i]); - assert(coin); + for (coin of items.values()) out.push(coin.toCoin()); - } return out; }; @@ -2330,11 +2299,11 @@ CoinIndex.prototype.insert = function insert(tx, index) { if (!addr) return; - items = this.index[addr]; + items = this.index.get(addr); if (!items) { items = new Map(); - this.index[addr] = items; + this.index.set(addr, items); } key = Outpoint.toKey(hash, index); @@ -2342,27 +2311,27 @@ CoinIndex.prototype.insert = function insert(tx, index) { assert(!items.has(key)); items.set(key, new IndexedCoin(tx, index)); - this.map[key] = addr; + this.map.set(key, addr); }; CoinIndex.prototype.remove = function remove(hash, index) { var key = Outpoint.toKey(hash, index); - var addr = this.map[key]; + var addr = this.map.get(key); var items; if (!addr) return; - items = this.index[addr]; + items = this.index.get(addr); assert(items); assert(items.has(key)); items.remove(key); if (items.size === 0) - delete this.index[addr]; + this.index.delete(addr); - delete this.map[key]; + this.map.delete(key); }; /** diff --git a/lib/mining/miner.js b/lib/mining/miner.js index 2b346baf..a7ba8161 100644 --- a/lib/mining/miner.js +++ b/lib/mining/miner.js @@ -258,8 +258,8 @@ Miner.prototype.assemble = function assemble(attempt) { var depMap = {}; var queue = new Heap(cmpRate); var priority = this.options.priorityWeight > 0; - var i, j, entry, item, tx, hash, input; - var prev, deps, hashes, weight, sigops, block; + var i, entry, item, tx, hash, input; + var prev, deps, weight, sigops, block; if (priority) queue.set(cmpPriority); @@ -272,19 +272,15 @@ Miner.prototype.assemble = function assemble(attempt) { assert(this.mempool.tip === this.chain.tip.hash, 'Mempool/chain tip mismatch! Unsafe to create block.'); - hashes = this.mempool.getSnapshot(); - - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; - entry = this.mempool.getEntry(hash); + for (entry of this.mempool.map.values()) { item = BlockEntry.fromEntry(entry, attempt); tx = item.tx; if (tx.isCoinbase()) throw new Error('Cannot add coinbase to block.'); - for (j = 0; j < tx.inputs.length; j++) { - input = tx.inputs[j]; + for (i = 0; i < tx.inputs.length; i++) { + input = tx.inputs[i]; prev = input.prevout.hash; if (!this.mempool.hasEntry(prev)) @@ -351,8 +347,8 @@ Miner.prototype.assemble = function assemble(attempt) { if (!deps) continue; - for (j = 0; j < deps.length; j++) { - item = deps[j]; + for (i = 0; i < deps.length; i++) { + item = deps[i]; if (--item.depCount === 0) queue.insert(item); } diff --git a/lib/net/bip152.js b/lib/net/bip152.js index 5b672b7a..191f97d8 100644 --- a/lib/net/bip152.js +++ b/lib/net/bip152.js @@ -311,16 +311,13 @@ CompactBlock.prototype.toRequest = function toRequest() { CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) { var have = {}; - var hashes = mempool.getSnapshot(); - var i, id, index, hash, tx; + var id, index, hash, entry, tx; if (this.count === this.totalTX) return true; - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; - tx = mempool.getTX(hash); - assert(tx); + for (entry of mempool.map.values()) { + tx = entry.tx; hash = tx.hash(); if (witness) diff --git a/lib/net/hostlist.js b/lib/net/hostlist.js index 8f0f663a..087882b6 100644 --- a/lib/net/hostlist.js +++ b/lib/net/hostlist.js @@ -15,7 +15,6 @@ var Network = require('../protocol/network'); var NetAddress = require('../primitives/netaddress'); var List = require('../utils/list'); var murmur3 = require('../utils/murmur3'); -var Map = require('../utils/map'); var common = require('./common'); var seeds = require('./seeds'); var dns = require('./dns'); @@ -42,14 +41,14 @@ function HostList(options) { this.dnsSeeds = []; this.dnsNodes = []; - this.map = {}; + this.map = new Map(); this.fresh = []; this.totalFresh = 0; this.used = []; this.totalUsed = 0; this.nodes = []; this.local = new Map(); - this.banned = {}; + this.banned = new Map(); this.timer = null; this.needsFlush = false; @@ -152,10 +151,8 @@ HostList.prototype._init = function init() { this.pushLocal(this.address, scores.MANUAL); this.addLocal(options.host, options.port, scores.BIND); - for (i = 0; i < hosts.length; i++) { - host = hosts[i]; + for (host of hosts) this.addLocal(host, port, scores.IF); - } }; /** @@ -231,10 +228,9 @@ HostList.prototype.stop = function stop() { HostList.prototype.injectSeeds = function injectSeeds() { var nodes = seeds.get(this.network.type); - var i, node, addr; + var node, addr; - for (i = 0; i < nodes.length; i++) { - node = nodes[i]; + for (node of nodes) { addr = NetAddress.fromHostname(node, this.network); if (!addr.isRoutable()) @@ -343,19 +339,15 @@ HostList.prototype.isFull = function isFull() { */ HostList.prototype.reset = function reset() { - var i, bucket; + var bucket; - this.map = {}; + this.map.clear(); - for (i = 0; i < this.fresh.length; i++) { - bucket = this.fresh[i]; + for (bucket of this.fresh) + bucket.clear(); + + for (bucket of this.used) bucket.reset(); - } - - for (i = 0; i < this.used.length; i++) { - bucket = this.used[i]; - bucket.reset(); - } this.totalFresh = 0; this.totalUsed = 0; @@ -369,7 +361,7 @@ HostList.prototype.reset = function reset() { */ HostList.prototype.ban = function ban(host) { - this.banned[host] = util.now(); + this.banned.set(host, util.now()); }; /** @@ -378,7 +370,7 @@ HostList.prototype.ban = function ban(host) { */ HostList.prototype.unban = function unban(host) { - delete this.banned[host]; + this.banned.delete(host); }; /** @@ -386,7 +378,7 @@ HostList.prototype.unban = function unban(host) { */ HostList.prototype.clearBanned = function clearBanned() { - this.banned = {}; + this.banned.clear(); }; /** @@ -396,13 +388,13 @@ HostList.prototype.clearBanned = function clearBanned() { */ HostList.prototype.isBanned = function isBanned(host) { - var time = this.banned[host]; + var time = this.banned.get(host); if (time == null) return false; if (util.now() > time + this.options.banTime) { - delete this.banned[host]; + this.banned.delete(host); return false; } @@ -418,7 +410,7 @@ HostList.prototype.getHost = function getHost() { var now = this.network.now(); var buckets = null; var factor = 1; - var index, key, bucket, entry, num; + var index, bucket, entry, num; if (this.totalFresh > 0) buckets = this.fresh; @@ -445,8 +437,11 @@ HostList.prototype.getHost = function getHost() { while (index--) entry = entry.next; } else { - key = bucket.keys()[index]; - entry = bucket.get(key); + for (entry of bucket.values()) { + if (index === 0) + break; + index--; + } } num = util.random(0, 1 << 30); @@ -507,7 +502,7 @@ HostList.prototype.add = function add(addr, src) { assert(addr.port !== 0); - entry = this.map[addr.hostname]; + entry = this.map.get(addr.hostname); if (entry) { // No source means we're inserting @@ -578,7 +573,7 @@ HostList.prototype.add = function add(addr, src) { bucket.set(entry.key(), entry); entry.refCount++; - this.map[entry.key()] = entry; + this.map.set(entry.key(), entry); this.needsFlush = true; return true; @@ -590,18 +585,14 @@ HostList.prototype.add = function add(addr, src) { */ HostList.prototype.evictFresh = function evictFresh(bucket) { - var keys = bucket.keys(); - var i, key, entry, old; - - for (i = 0; i < keys.length; i++) { - key = keys[i]; - entry = bucket.get(key); + var entry, old; + for (entry of bucket.values()) { if (this.isStale(entry)) { - bucket.remove(entry.key()); + bucket.delete(entry.key()); if (--entry.refCount === 0) { - delete this.map[entry.key()]; + this.map.delete(entry.key()); this.totalFresh--; } @@ -620,10 +611,10 @@ HostList.prototype.evictFresh = function evictFresh(bucket) { if (!old) return; - bucket.remove(old.key()); + bucket.delete(old.key()); if (--old.refCount === 0) { - delete this.map[old.key()]; + this.map.delete(old.key()); this.totalFresh--; } }; @@ -667,7 +658,7 @@ HostList.prototype.isStale = function isStale(entry) { */ HostList.prototype.remove = function remove(hostname) { - var entry = this.map[hostname]; + var entry = this.map.get(hostname); var i, head, bucket; if (!entry) @@ -680,8 +671,7 @@ HostList.prototype.remove = function remove(hostname) { while (head.prev) head = head.prev; - for (i = 0; i < this.used.length; i++) { - bucket = this.used[i]; + for (bucket of this.used) { if (bucket.head === head) { bucket.remove(entry); this.totalUsed--; @@ -691,9 +681,8 @@ HostList.prototype.remove = function remove(hostname) { assert(i < this.used.length); } else { - for (i = 0; i < this.fresh.length; i++) { - bucket = this.fresh[i]; - if (bucket.remove(entry.key())) + for (bucket of this.fresh) { + if (bucket.delete(entry.key())) entry.refCount--; } @@ -701,7 +690,7 @@ HostList.prototype.remove = function remove(hostname) { assert(entry.refCount === 0); } - delete this.map[entry.key()]; + this.map.delete(entry.key()); return entry.addr; }; @@ -712,7 +701,7 @@ HostList.prototype.remove = function remove(hostname) { */ HostList.prototype.markAttempt = function markAttempt(hostname) { - var entry = this.map[hostname]; + var entry = this.map.get(hostname); var now = this.network.now(); if (!entry) @@ -728,7 +717,7 @@ HostList.prototype.markAttempt = function markAttempt(hostname) { */ HostList.prototype.markSuccess = function markSuccess(hostname) { - var entry = this.map[hostname]; + var entry = this.map.get(hostname); var now = this.network.now(); if (!entry) @@ -745,9 +734,9 @@ HostList.prototype.markSuccess = function markSuccess(hostname) { */ HostList.prototype.markAck = function markAck(hostname, services) { - var entry = this.map[hostname]; + var entry = this.map.get(hostname); var now = this.network.now(); - var i, bucket, evicted, old, fresh; + var bucket, evicted, old, fresh; if (!entry) return; @@ -765,9 +754,8 @@ HostList.prototype.markAck = function markAck(hostname, services) { assert(entry.refCount > 0); // Remove from fresh. - for (i = 0; i < this.fresh.length; i++) { - bucket = this.fresh[i]; - if (bucket.remove(entry.key())) { + for (bucket of this.fresh) { + if (bucket.delete(entry.key())) { entry.refCount--; old = bucket; } @@ -830,15 +818,11 @@ HostList.prototype.evictUsed = function evictUsed(bucket) { */ HostList.prototype.toArray = function toArray() { - var keys = Object.keys(this.map); var out = []; - var i, key, entry; + var entry; - for (i = 0; i < keys.length; i++) { - key = keys[i]; - entry = this.map[key]; + for (entry of this.map.values()) out.push(entry.addr); - } assert.equal(out.length, this.size()); @@ -993,21 +977,18 @@ HostList.prototype.pushLocal = function pushLocal(addr, score) { */ HostList.prototype.getLocal = function getLocal(src) { - var keys = this.local.keys(); var bestReach = -1; var bestScore = -1; var bestDest = null; - var i, key, dest, reach; + var dest, reach; if (!src) src = this.address; - if (keys.length === 0) + if (this.local.length === 0) return null; - for (i = 0; i < keys.length; i++) { - key = keys[i]; - dest = this.local.get(key); + for (dest of this.local.values()) { reach = src.getReachability(dest.addr); if (reach < bestReach) @@ -1121,7 +1102,7 @@ HostList.prototype.populateSeed = async function populateSeed(seed) { HostList.prototype.populate = async function populate(target) { var addrs = []; - var i, addr, hosts, host; + var addr, hosts, host; assert(target.type === IP.types.DNS, 'Resolved host passed.'); @@ -1134,8 +1115,7 @@ HostList.prototype.populate = async function populate(target) { return addrs; } - for (i = 0; i < hosts.length; i++) { - host = hosts[i]; + for (host of hosts) { addr = NetAddress.fromHost(host, target.port, this.network); addrs.push(addr); } @@ -1152,24 +1132,19 @@ HostList.prototype.toJSON = function toJSON() { var addrs = []; var fresh = []; var used = []; - var i, keys, key, bucket, entry; + var bucket, entry, key, keys; - keys = Object.keys(this.map); - - for (i = 0; i < keys.length; i++) { - key = keys[i]; - entry = this.map[key]; + for (entry of this.map.values()) addrs.push(entry.toJSON()); - } - for (i = 0; i < this.fresh.length; i++) { - bucket = this.fresh[i]; - keys = bucket.keys(); + for (bucket of this.fresh) { + keys = []; + for (key of bucket.keys()) + keys.push(key); fresh.push(keys); } - for (i = 0; i < this.used.length; i++) { - bucket = this.used[i]; + for (bucket of this.used) { keys = []; for (entry = bucket.head; entry; entry = entry.next) keys.push(entry.key()); @@ -1193,12 +1168,12 @@ HostList.prototype.toJSON = function toJSON() { HostList.prototype.fromJSON = function fromJSON(json) { var sources = {}; - var map = {}; + var map = new Map(); var fresh = []; var totalFresh = 0; var used = []; var totalUsed = 0; - var i, j, bucket, keys, key, addr, entry, src; + var i, bucket, keys, key, addr, entry, src; assert(json && typeof json === 'object'); @@ -1207,8 +1182,7 @@ HostList.prototype.fromJSON = function fromJSON(json) { assert(Array.isArray(json.addrs)); - for (i = 0; i < json.addrs.length; i++) { - addr = json.addrs[i]; + for (addr of json.addrs) { entry = HostEntry.fromJSON(addr, this.network); src = sources[entry.src.hostname]; @@ -1220,20 +1194,18 @@ HostList.prototype.fromJSON = function fromJSON(json) { entry.src = src; - map[entry.key()] = entry; + map.set(entry.key(), entry); } assert(Array.isArray(json.fresh)); assert(json.fresh.length <= this.options.maxBuckets, 'Buckets mismatch.'); - for (i = 0; i < json.fresh.length; i++) { - keys = json.fresh[i]; + for (keys of json.fresh) { bucket = new Map(); - for (j = 0; j < keys.length; j++) { - key = keys[j]; - entry = map[key]; + for (key of keys) { + entry = map.get(key); assert(entry); if (entry.refCount === 0) totalFresh++; @@ -1258,9 +1230,8 @@ HostList.prototype.fromJSON = function fromJSON(json) { keys = json.used[i]; bucket = new List(); - for (j = 0; j < keys.length; j++) { - key = keys[j]; - entry = map[key]; + for (key of keys) { + entry = map.get(key); assert(entry); assert(entry.refCount === 0); assert(!entry.used); @@ -1278,13 +1249,8 @@ HostList.prototype.fromJSON = function fromJSON(json) { assert(used.length === this.used.length, 'Buckets mismatch.'); - keys = Object.keys(map); - - for (i = 0; i < keys.length; i++) { - key = keys[i]; - entry = map[key]; + for (entry of map.values()) assert(entry.used || entry.refCount > 0); - } this.map = map; this.fresh = fresh; diff --git a/lib/net/peer.js b/lib/net/peer.js index 0325735c..0aeb1731 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -11,7 +11,6 @@ var assert = require('assert'); var EventEmitter = require('events').EventEmitter; var util = require('../utils/util'); var co = require('../utils/co'); -var Map = require('../utils/map'); var Parser = require('./parser'); var Framer = require('./framer'); var packets = require('./packets'); @@ -1053,7 +1052,7 @@ Peer.prototype.sendFeeRate = function sendFeeRate(rate) { Peer.prototype.destroy = function destroy() { var connected = this.connected; - var i, keys, cmd, entry, jobs, job; + var i, cmd, entry, jobs, job; if (this.destroyed) return; @@ -1100,12 +1099,8 @@ Peer.prototype.destroy = function destroy() { job.reject(new Error('Peer was destroyed.')); } - keys = this.responseMap.keys(); - - for (i = 0; i < keys.length; i++) { - cmd = keys[i]; - entry = this.responseMap.get(cmd); - this.responseMap.remove(cmd); + for ([cmd, entry] of this.responseMap) { + this.responseMap.delete(cmd); entry.reject(new Error('Peer was destroyed.')); } @@ -1288,13 +1283,10 @@ Peer.prototype.fulfill = function fulfill(packet) { */ Peer.prototype.maybeTimeout = function maybeTimeout() { - var keys = this.responseMap.keys(); var now = util.ms(); - var i, key, entry, name, ts, block, mult; + var key, entry, name, ts, block, mult; - for (i = 0; i < keys.length; i++) { - key = keys[i]; - entry = this.responseMap.get(key); + for ([key, entry] of this.responseMap) { if (now > entry.timeout) { name = packets.typesByVal[key]; this.error('Peer is stalling (%s).', name.toLowerCase()); @@ -1321,11 +1313,7 @@ Peer.prototype.maybeTimeout = function maybeTimeout() { } if (this.options.isFull() || !this.syncing) { - keys = this.blockMap.keys(); - - for (i = 0; i < keys.length; i++) { - key = keys[i]; - ts = this.blockMap.get(key); + for (ts of this.blockMap.values()) { if (now > ts + Peer.BLOCK_TIMEOUT) { this.error('Peer is stalling (block).'); this.destroy(); @@ -1333,11 +1321,7 @@ Peer.prototype.maybeTimeout = function maybeTimeout() { } } - keys = this.txMap.keys(); - - for (i = 0; i < keys.length; i++) { - key = keys[i]; - ts = this.txMap.get(key); + for (ts of this.txMap.values()) { if (now > ts + Peer.TX_TIMEOUT) { this.error('Peer is stalling (tx).'); this.destroy(); @@ -1345,11 +1329,7 @@ Peer.prototype.maybeTimeout = function maybeTimeout() { } } - keys = this.compactBlocks.keys(); - - for (i = 0; i < keys.length; i++) { - key = keys[i]; - block = this.compactBlocks.get(key); + for (block of this.compactBlocks.values()) { if (now > block.now + Peer.RESPONSE_TIMEOUT) { this.error('Peer is stalling (blocktxn).'); this.destroy(); @@ -1426,7 +1406,7 @@ Peer.prototype.response = function response(type, payload) { if (!entry) return; - this.responseMap.remove(type); + this.responseMap.delete(type); return entry; }; diff --git a/lib/net/pool.js b/lib/net/pool.js index eb419364..1844a191 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -32,7 +32,6 @@ var dns = require('./dns'); var HostList = require('./hostlist'); var UPNP = require('./upnp'); var InvItem = require('../primitives/invitem'); -var Map = require('../utils/map'); var packets = require('./packets'); var services = common.services; var invTypes = InvItem.types; @@ -94,9 +93,9 @@ function Pool(options) { this.syncing = false; this.spvFilter = null; this.txFilter = null; - this.blockMap = new Map(); - this.txMap = new Map(); - this.compactBlocks = new Map(); + this.blockMap = new Set(); + this.txMap = new Set(); + this.compactBlocks = new Set(); this.invMap = new Map(); this.pendingFilter = null; this.pendingRefill = null; @@ -345,7 +344,7 @@ Pool.prototype.disconnect = async function disconnect() { */ Pool.prototype._disconnect = async function disconnect() { - var i, item, hashes, hash; + var item; assert(this.loaded, 'Pool is not loaded.'); @@ -354,18 +353,13 @@ Pool.prototype._disconnect = async function disconnect() { this.disconnecting = true; - hashes = this.invMap.keys(); - - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; - item = this.invMap.get(hash); + for (item of this.invMap.values()) item.resolve(); - } this.peers.destroy(); - this.blockMap.reset(); - this.txMap.reset(); + this.blockMap.clear(); + this.txMap.clear(); if (this.pendingFilter != null) { clearTimeout(this.pendingFilter); @@ -761,11 +755,11 @@ Pool.prototype.stopSync = function stopSync() { peer.merkleMap = null; peer.blockTime = -1; peer.blockMap.reset(); - peer.compactBlocks.reset(); + peer.compactBlocks.clear(); } - this.blockMap.reset(); - this.compactBlocks.reset(); + this.blockMap.clear(); + this.compactBlocks.clear(); }; /** @@ -986,13 +980,9 @@ Pool.prototype.getNextTip = function getNextTip(height) { Pool.prototype.announceList = function announceList(peer) { var blocks = []; var txs = []; - var hashes = this.invMap.keys(); - var i, hash, item; - - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; - item = this.invMap.get(hash); + var item; + for (item of this.invMap.values()) { switch (item.type) { case invTypes.BLOCK: blocks.push(item.msg); @@ -2481,7 +2471,7 @@ Pool.prototype.logStatus = function logStatus(block) { util.date(block.ts), this.chain.height, (this.chain.getProgress() * 100).toFixed(2) + '%', - this.chain.orphanCount, + this.chain.orphanMap.size, this.blockMap.size, block.bits, this.peers.size()); @@ -2543,7 +2533,7 @@ Pool.prototype._handleTX = async function handleTX(peer, packet) { return; } - peer.merkleMap.insert(hash); + peer.merkleMap.add(hash); block.addTX(tx); @@ -2776,7 +2766,7 @@ Pool.prototype._handleMerkleBlock = async function handleMerkleBlock(peer, packe peer.merkleBlock = block; peer.merkleTime = util.ms(); peer.merkleMatches = block.tree.matches.length; - peer.merkleMap = new Map(); + peer.merkleMap = new Set(); }; /** @@ -2861,7 +2851,7 @@ Pool.prototype.handleCmpctBlock = async function handleCmpctBlock(peer, packet) } peer.blockMap.set(hash, util.ms()); assert(!this.blockMap.has(hash)); - this.blockMap.insert(hash); + this.blockMap.add(hash); } if (!this.mempool) { @@ -2919,7 +2909,7 @@ Pool.prototype.handleCmpctBlock = async function handleCmpctBlock(peer, packet) assert(!peer.compactBlocks.has(hash)); peer.compactBlocks.set(hash, block); - this.compactBlocks.insert(hash); + this.compactBlocks.add(hash); this.logger.debug( 'Received non-full compact block %s tx=%d/%d (%s).', @@ -3000,10 +2990,10 @@ Pool.prototype.handleBlockTxn = async function handleBlockTxn(peer, packet) { return; } - peer.compactBlocks.remove(res.hash); + peer.compactBlocks.delete(res.hash); assert(this.compactBlocks.has(res.hash)); - this.compactBlocks.remove(res.hash); + this.compactBlocks.delete(res.hash); if (!block.fillMissing(res)) { this.logger.warning( @@ -3248,33 +3238,22 @@ Pool.prototype.refill = function refill() { */ Pool.prototype.removePeer = function removePeer(peer) { - var i, hashes, hash; + var hash; this.peers.remove(peer); - hashes = peer.blockMap.keys(); - - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; + for (hash of peer.blockMap.keys()) this.resolveBlock(peer, hash); - } - hashes = peer.txMap.keys(); - - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; + for (hash of peer.txMap.keys()) this.resolveTX(peer, hash); - } - hashes = peer.compactBlocks.keys(); - - for (i = 0; i < hashes.length; i++) { - hash = hashes[i]; + for (hash of peer.compactBlocks.keys()) { assert(this.compactBlocks.has(hash)); - this.compactBlocks.remove(hash); + this.compactBlocks.delete(hash); } - peer.compactBlocks.reset(); + peer.compactBlocks.clear(); }; /** @@ -3469,7 +3448,7 @@ Pool.prototype.getBlock = function getBlock(peer, hashes) { if (this.blockMap.has(hash)) continue; - this.blockMap.insert(hash); + this.blockMap.add(hash); peer.blockMap.set(hash, now); if (this.chain.synced) @@ -3516,7 +3495,7 @@ Pool.prototype.getTX = function getTX(peer, hashes) { if (this.txMap.has(hash)) continue; - this.txMap.insert(hash); + this.txMap.add(hash); peer.txMap.set(hash, now); now += 50; @@ -3620,10 +3599,10 @@ Pool.prototype.resolveTX = function resolveTX(peer, hash) { if (!peer.txMap.has(hash)) return false; - peer.txMap.remove(hash); + peer.txMap.delete(hash); assert(this.txMap.has(hash)); - this.txMap.remove(hash); + this.txMap.delete(hash); return true; }; @@ -3639,10 +3618,10 @@ Pool.prototype.resolveBlock = function resolveBlock(peer, hash) { if (!peer.blockMap.has(hash)) return false; - peer.blockMap.remove(hash); + peer.blockMap.delete(hash); assert(this.blockMap.has(hash)); - this.blockMap.remove(hash); + this.blockMap.delete(hash); return true; }; @@ -4168,8 +4147,8 @@ PoolOptions.prototype._resolve = function resolve(name) { */ function PeerList() { - this.map = {}; - this.ids = {}; + this.map = new Map(); + this.ids = new Map(); this.list = new List(); this.load = null; this.inbound = 0; @@ -4211,11 +4190,11 @@ PeerList.prototype.size = function size() { PeerList.prototype.add = function add(peer) { assert(this.list.push(peer)); - assert(!this.map[peer.hostname()]); - this.map[peer.hostname()] = peer; + assert(!this.map.has(peer.hostname())); + this.map.set(peer.hostname(), peer); - assert(!this.ids[peer.id]); - this.ids[peer.id] = peer; + assert(!this.ids.has(peer.id)); + this.ids.set(peer.id, peer); if (peer.outbound) this.outbound++; @@ -4231,11 +4210,11 @@ PeerList.prototype.add = function add(peer) { PeerList.prototype.remove = function remove(peer) { assert(this.list.remove(peer)); - assert(this.ids[peer.id]); - delete this.ids[peer.id]; + assert(this.ids.has(peer.id)); + this.ids.delete(peer.id); - assert(this.map[peer.hostname()]); - delete this.map[peer.hostname()]; + assert(this.map.has(peer.hostname())); + this.map.delete(peer.hostname()); if (peer === this.load) { assert(peer.loader); @@ -4256,7 +4235,7 @@ PeerList.prototype.remove = function remove(peer) { */ PeerList.prototype.get = function get(hostname) { - return this.map[hostname]; + return this.map.get(hostname); }; /** @@ -4266,7 +4245,7 @@ PeerList.prototype.get = function get(hostname) { */ PeerList.prototype.has = function has(hostname) { - return this.map[hostname] != null; + return this.map.has(hostname); }; /** @@ -4276,7 +4255,7 @@ PeerList.prototype.has = function has(hostname) { */ PeerList.prototype.find = function find(id) { - return this.ids[id]; + return this.ids.get(id); }; /** @@ -4394,7 +4373,7 @@ BroadcastItem.prototype.cleanup = function cleanup() { clearTimeout(this.timeout); this.timeout = null; - this.pool.invMap.remove(this.hash); + this.pool.invMap.delete(this.hash); }; /** @@ -4490,8 +4469,8 @@ BroadcastItem.prototype.inspect = function inspect() { */ function NonceList() { - this.map = {}; - this.hosts = {}; + this.map = new Map(); + this.hosts = new Map(); } NonceList.prototype.alloc = function alloc(hostname) { @@ -4500,10 +4479,10 @@ NonceList.prototype.alloc = function alloc(hostname) { for (;;) { nonce = util.nonce(); key = nonce.toString('hex'); - if (!this.map[key]) { - this.map[key] = hostname; - assert(!this.hosts[hostname]); - this.hosts[hostname] = key; + if (!this.map.has(key)) { + this.map.set(key, hostname); + assert(!this.hosts.has(hostname)); + this.hosts.set(hostname, key); break; } } @@ -4513,19 +4492,19 @@ NonceList.prototype.alloc = function alloc(hostname) { NonceList.prototype.has = function has(nonce) { var key = nonce.toString('hex'); - return this.map[key] != null; + return this.map.has(key); }; NonceList.prototype.remove = function remove(hostname) { - var key = this.hosts[hostname]; + var key = this.hosts.get(hostname); if (!key) return false; - delete this.hosts[hostname]; + this.hosts.delete(hostname); - assert(this.map[key]); - delete this.map[key]; + assert(this.map.has(key)); + this.map.delete(key); return true; }; diff --git a/lib/protocol/timedata.js b/lib/protocol/timedata.js index cdb85f99..64256a23 100644 --- a/lib/protocol/timedata.js +++ b/lib/protocol/timedata.js @@ -34,7 +34,7 @@ function TimeData(limit) { limit = 200; this.samples = []; - this.known = {}; + this.known = new Map(); this.limit = limit; this.offset = 0; this._checked = false; @@ -55,10 +55,10 @@ TimeData.prototype.add = function add(id, time) { if (this.samples.length >= this.limit) return; - if (this.known[id] != null) + if (this.known.has(id)) return; - this.known[id] = sample; + this.known.set(id, sample); util.binaryInsert(this.samples, sample, compare); diff --git a/lib/script/sigcache.js b/lib/script/sigcache.js index 7a2a093c..ee275b12 100644 --- a/lib/script/sigcache.js +++ b/lib/script/sigcache.js @@ -32,7 +32,7 @@ function SigCache(size) { this.size = size; this.keys = []; - this.valid = {}; + this.valid = new Map(); } /** @@ -46,7 +46,7 @@ SigCache.prototype.resize = function resize(size) { this.size = size; this.keys.length = 0; - this.valid = {}; + this.valid.clear(); }; /** @@ -63,12 +63,12 @@ SigCache.prototype.add = function add(hash, sig, key) { if (this.size === 0) return; - this.valid[hash] = new SigCacheEntry(sig, key); + this.valid.set(hash, new SigCacheEntry(sig, key)); if (this.keys.length >= this.size) { i = Math.floor(Math.random() * this.keys.length); k = this.keys[i]; - delete this.valid[k]; + this.valid.delete(k); this.keys[i] = hash; } else { this.keys.push(hash); @@ -84,7 +84,7 @@ SigCache.prototype.add = function add(hash, sig, key) { */ SigCache.prototype.has = function has(hash, sig, key) { - var entry = this.valid[hash]; + var entry = this.valid.get(hash); if (!entry) return false; diff --git a/lib/utils/lru.js b/lib/utils/lru.js index e177c7f9..ac91848d 100644 --- a/lib/utils/lru.js +++ b/lib/utils/lru.js @@ -21,7 +21,7 @@ function LRU(capacity, getSize) { if (!(this instanceof LRU)) return new LRU(capacity, getSize); - this.map = Object.create(null); + this.map = new Map(); this.size = 0; this.items = 0; this.head = null; @@ -70,7 +70,7 @@ LRU.prototype._compact = function _compact() { break; this.size -= this._getSize(item); this.items--; - delete this.map[item.key]; + this.map.delete(item.key); next = item.next; item.prev = null; item.next = null; @@ -94,7 +94,7 @@ LRU.prototype.reset = function reset() { var item, next; for (item = this.head; item; item = next) { - delete this.map[item.key]; + this.map.delete(item.key); this.items--; next = item.next; item.prev = null; @@ -122,7 +122,7 @@ LRU.prototype.set = function set(key, value) { key = key + ''; - item = this.map[key]; + item = this.map.get(key); if (item) { this.size -= this._getSize(item); @@ -136,7 +136,7 @@ LRU.prototype.set = function set(key, value) { item = new LRUItem(key, value); - this.map[key] = item; + this.map.set(key, item); this._appendList(item); @@ -160,7 +160,7 @@ LRU.prototype.get = function get(key) { key = key + ''; - item = this.map[key]; + item = this.map.get(key); if (!item) return; @@ -180,7 +180,7 @@ LRU.prototype.get = function get(key) { LRU.prototype.has = function get(key) { if (this.capacity === 0) return false; - return this.map[key] != null; + return this.map.has(key + ''); }; /** @@ -197,7 +197,7 @@ LRU.prototype.remove = function remove(key) { key = key + ''; - item = this.map[key]; + item = this.map.get(key); if (!item) return false; @@ -205,7 +205,7 @@ LRU.prototype.remove = function remove(key) { this.size -= this._getSize(item); this.items--; - delete this.map[key]; + this.map.delete(key); this._removeList(item); diff --git a/lib/utils/map.js b/lib/utils/map.js deleted file mode 100644 index 7883bc9e..00000000 --- a/lib/utils/map.js +++ /dev/null @@ -1,136 +0,0 @@ -/*! - * map.js - hash table for bcoin - * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). - * https://github.com/bcoin-org/bcoin - */ - -'use strict'; - -var assert = require('assert'); - -/** - * Map - * @alias module:utils.Map - * @constructor - */ - -function Map() { - if (!(this instanceof Map)) - return new Map(); - - this.map = Object.create(null); - this.size = 0; -} - -/** - * Get map keys. - * @returns {String[]} - */ - -Map.prototype.keys = function keys() { - return Object.keys(this.map); -}; - -/** - * Get map values. - * @returns {Object[]} - */ - -Map.prototype.values = function values() { - var keys = Object.keys(this.map); - var values = []; - var i, key; - - for (i = 0; i < keys.length; i++) { - key = keys[i]; - values.push(this.map[key]); - } - - return values; -}; - -/** - * Get item from map. - * @param {String} key - * @returns {Object|null} - */ - -Map.prototype.get = function get(key) { - return this.map[key]; -}; - -/** - * Test whether map has an item. - * @param {String} key - * @returns {Boolean} - */ - -Map.prototype.has = function has(key) { - return this.map[key] !== undefined; -}; - -/** - * Set a key to value in map. - * @param {String} key - * @param {Object} value - * @returns {Boolean} - */ - -Map.prototype.set = function set(key, value) { - var item = this.map[key]; - - assert(value !== undefined); - - this.map[key] = value; - - if (item === undefined) { - this.size++; - return true; - } - - return false; -}; - -/** - * Remove an item from map. - * @param {String} key - * @returns {Object|null} - */ - -Map.prototype.remove = function remove(key) { - var item = this.map[key]; - - if (item === undefined) - return; - - delete this.map[key]; - this.size--; - - return item; -}; - -/** - * Reset the map. - */ - -Map.prototype.reset = function reset() { - this.map = Object.create(null); - this.size = 0; -}; - -/** - * Insert a key. - * Equivalent to `this.set([key], true)`. - * @param {String} key - * @returns {Boolean} - */ - -Map.prototype.insert = function insert(key) { - return this.set(key, true); -}; - -/* - * Expose - */ - -module.exports = Map; diff --git a/lib/utils/mappedlock.js b/lib/utils/mappedlock.js index f41735d0..19ba54c0 100644 --- a/lib/utils/mappedlock.js +++ b/lib/utils/mappedlock.js @@ -20,8 +20,8 @@ function MappedLock() { if (!(this instanceof MappedLock)) return MappedLock.create(); - this.jobs = Object.create(null); - this.busy = Object.create(null); + this.jobs = new Map(); + this.busy = new Set(); this.destroyed = false; } @@ -45,7 +45,7 @@ MappedLock.create = function create() { */ MappedLock.prototype.has = function has(name) { - return this.busy[name] === true; + return this.busy.has(name); }; /** @@ -56,7 +56,7 @@ MappedLock.prototype.has = function has(name) { */ MappedLock.prototype.hasPending = function hasPending(name) { - return this.jobs[name] != null; + return this.jobs.has(name); }; /** @@ -80,19 +80,19 @@ MappedLock.prototype.lock = function lock(key, force) { return Promise.resolve(nop); if (force) { - assert(this.busy[key]); + assert(this.busy.has(key)); return Promise.resolve(nop); } - if (this.busy[key]) { + if (this.busy.has(key)) { return new Promise(function(resolve, reject) { - if (!self.jobs[key]) - self.jobs[key] = []; - self.jobs[key].push(new Job(resolve, reject)); + if (!self.jobs.has(key)) + self.jobs.set(key, []); + self.jobs.get(key).push(new Job(resolve, reject)); }); } - this.busy[key] = true; + this.busy.add(key); return Promise.resolve(this.unlock(key)); }; @@ -107,11 +107,11 @@ MappedLock.prototype.lock = function lock(key, force) { MappedLock.prototype.unlock = function unlock(key) { var self = this; return function unlocker() { - var jobs = self.jobs[key]; + var jobs = self.jobs.get(key); var job; - assert(self.destroyed || self.busy[key]); - delete self.busy[key]; + assert(self.destroyed || self.busy.has(key)); + self.busy.delete(key); if (!jobs) return; @@ -122,9 +122,9 @@ MappedLock.prototype.unlock = function unlock(key) { assert(job); if (jobs.length === 0) - delete self.jobs[key]; + self.jobs.delete(key); - self.busy[key] = true; + self.busy.add(key); job.resolve(unlocker); }; @@ -137,23 +137,18 @@ MappedLock.prototype.unlock = function unlock(key) { MappedLock.prototype.destroy = function destroy() { var err = new Error('Lock was destroyed.'); var map = this.jobs; - var keys = Object.keys(map); - var i, j, key, jobs, job; + var jobs, job; assert(!this.destroyed, 'Lock is already destroyed.'); this.destroyed = true; - this.jobs = Object.create(null); - this.busy = Object.create(null); + this.jobs = new Map(); + this.busy = new Map(); - for (i = 0; i < keys.length; i++) { - key = keys[i]; - jobs = map[key]; - for (j = 0; j < jobs.length; j++) { - job = jobs[j]; + for (jobs of map.values()) { + for (job of jobs) job.reject(err); - } } }; @@ -163,7 +158,6 @@ MappedLock.prototype.destroy = function destroy() { * @ignore * @param {Function} resolve * @param {Function} reject - * @param {String?} name */ function Job(resolve, reject) { diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index baa55582..cdddea94 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -45,7 +45,7 @@ function TXDB(wallet) { this.options = wallet.db.options; this.coinCache = new LRU(10000); - this.locked = {}; + this.locked = new Set(); this.state = null; this.pending = null; this.events = []; @@ -1612,7 +1612,7 @@ TXDB.prototype.unlockTX = function unlockTX(tx) { TXDB.prototype.lockCoin = function lockCoin(coin) { var key = coin.toKey(); - this.locked[key] = true; + this.locked.add(key); }; /** @@ -1622,7 +1622,7 @@ TXDB.prototype.lockCoin = function lockCoin(coin) { TXDB.prototype.unlockCoin = function unlockCoin(coin) { var key = coin.toKey(); - delete this.locked[key]; + return this.locked.delete(key); }; /** @@ -1632,7 +1632,7 @@ TXDB.prototype.unlockCoin = function unlockCoin(coin) { TXDB.prototype.isLocked = function isLocked(coin) { var key = coin.toKey(); - return this.locked[key] === true; + return this.locked.has(key); }; /** @@ -1661,14 +1661,11 @@ TXDB.prototype.filterLocked = function filterLocked(coins) { */ TXDB.prototype.getLocked = function getLocked() { - var keys = Object.keys(this.locked); var outpoints = []; - var i, key; + var key; - for (i = 0; i < keys.length; i++) { - key = keys[i]; + for (key of this.locked.keys()) outpoints.push(Outpoint.fromKey(key)); - } return outpoints; }; diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index 4c0c61be..8e9b4ac2 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -84,7 +84,7 @@ function WalletDB(options) { } this.state = new ChainState(); - this.wallets = Object.create(null); + this.wallets = new Map(); this.depth = 0; this.rescanning = false; this.bound = false; @@ -182,19 +182,15 @@ WalletDB.prototype._open = async function open() { */ WalletDB.prototype._close = async function close() { - var keys = Object.keys(this.wallets); - var i, key, wallet; + var wallet; await this.disconnect(); if (this.http && this.options.listen) await this.http.close(); - for (i = 0; i < keys.length; i++) { - key = keys[i]; - wallet = this.wallets[key]; + for (wallet of this.wallets.values()) await wallet.destroy(); - } await this.db.close(); @@ -809,8 +805,8 @@ WalletDB.prototype.dump = function dump() { */ WalletDB.prototype.register = function register(wallet) { - assert(!this.wallets[wallet.wid]); - this.wallets[wallet.wid] = wallet; + assert(!this.wallets.has(wallet.wid)); + this.wallets.set(wallet.wid, wallet); }; /** @@ -820,8 +816,8 @@ WalletDB.prototype.register = function register(wallet) { */ WalletDB.prototype.unregister = function unregister(wallet) { - assert(this.wallets[wallet.wid]); - delete this.wallets[wallet.wid]; + assert(this.wallets.has(wallet.wid)); + this.wallets.delete(wallet.wid); }; /** @@ -886,7 +882,7 @@ WalletDB.prototype.get = async function get(id) { */ WalletDB.prototype._get = async function get(wid) { - var wallet = this.wallets[wid]; + var wallet = this.wallets.get(wid); var data; if (wallet) diff --git a/lib/workers/workerpool.js b/lib/workers/workerpool.js index efb0c356..15d043f5 100644 --- a/lib/workers/workerpool.js +++ b/lib/workers/workerpool.js @@ -484,7 +484,7 @@ function Worker(id) { this.id = id != null ? id : -1; this.child = null; - this.pending = {}; + this.pending = new Map(); this.env = { BCOIN_MASTER_URL: process.env.BCOIN_MASTER_URL || WorkerPool.MASTER_URL, @@ -777,9 +777,9 @@ Worker.prototype.execute = function execute(packet, timeout) { Worker.prototype._execute = function _execute(packet, timeout, resolve, reject) { var job = new PendingJob(this, packet.id, resolve, reject); - assert(!this.pending[packet.id], 'ID overflow.'); + assert(!this.pending.has(packet.id), 'ID overflow.'); - this.pending[packet.id] = job; + this.pending.set(packet.id, job); job.start(timeout); @@ -793,7 +793,7 @@ Worker.prototype._execute = function _execute(packet, timeout, resolve, reject) */ Worker.prototype.resolveJob = function resolveJob(id, result) { - var job = this.pending[id]; + var job = this.pending.get(id); if (!job) throw new Error('Job ' + id + ' is not in progress.'); @@ -808,7 +808,7 @@ Worker.prototype.resolveJob = function resolveJob(id, result) { */ Worker.prototype.rejectJob = function rejectJob(id, err) { - var job = this.pending[id]; + var job = this.pending.get(id); if (!job) throw new Error('Job ' + id + ' is not in progress.'); @@ -821,14 +821,10 @@ Worker.prototype.rejectJob = function rejectJob(id, err) { */ Worker.prototype.killJobs = function killJobs() { - var keys = Object.keys(this.pending); - var i, key, job; + var job; - for (i = 0; i < keys.length; i++) { - key = keys[i]; - job = this.pending[key]; + for (job of this.pending.values()) job.destroy(); - } }; /** @@ -889,8 +885,8 @@ PendingJob.prototype.cleanup = function cleanup() { this.timer = null; } - assert(this.worker.pending[this.id]); - delete this.worker.pending[this.id]; + assert(this.worker.pending.has(this.id)); + this.worker.pending.delete(this.id); return job; }; diff --git a/test/block-test.js b/test/block-test.js index 11c43183..13150ccb 100644 --- a/test/block-test.js +++ b/test/block-test.js @@ -294,7 +294,7 @@ describe('Block', function() { var block = Block.fromRaw(cmpct1[1], 'hex'); var cblock1 = bip152.CompactBlock.fromRaw(cmpct1[0], 'hex'); var cblock2 = bip152.CompactBlock.fromBlock(block, false, cblock1.keyNonce); - var map = {}; + var map = new Map(); var i, tx, mempool, result; assert(cblock1.init()); @@ -304,16 +304,11 @@ describe('Block', function() { for (i = 0; i < block.txs.length; i++) { tx = block.txs[i]; - map[tx.hash('hex')] = tx; + map.set(tx.hash('hex'), { tx: tx }); } mempool = { - getSnapshot: function() { - return Object.keys(map); - }, - getTX: function(hash) { - return map[hash]; - } + map: map }; assert.equal(cblock1.sid(block.txs[1].hash()), 125673511480291); @@ -333,29 +328,21 @@ describe('Block', function() { var block = Block.fromRaw(cmpct1[1], 'hex'); var cblock1 = bip152.CompactBlock.fromRaw(cmpct1[0], 'hex'); var cblock2 = bip152.CompactBlock.fromBlock(block, false, cblock1.keyNonce); - var map = {}; - var i, tx, mid, keys, mempool, result, req, res; + var map = new Map(); + var i, tx, mempool, result, req, res; assert(cblock1.init()); assert.equal(cblock1.toRaw().toString('hex'), cmpct1[0]); assert.equal(cblock2.toRaw().toString('hex'), cmpct1[0]); - for (i = 0; i < block.txs.length; i++) { + for (i = 0; i < block.txs.length >>> 1; i++) { tx = block.txs[i]; - map[tx.hash('hex')] = tx; + map.set(tx.hash('hex'), { tx: tx }); } - mid = block.txs.length >>> 1; - keys = Object.keys(map).slice(0, mid); - mempool = { - getSnapshot: function() { - return keys; - }, - getTX: function(hash) { - return map[hash]; - } + map: map }; assert.equal(cblock1.sid(block.txs[1].hash()), 125673511480291); @@ -389,7 +376,7 @@ describe('Block', function() { var block = Block.fromRaw(cmpct2block); var cblock1 = bip152.CompactBlock.fromRaw(cmpct2, 'hex'); var cblock2 = bip152.CompactBlock.fromBlock(block, false, cblock1.keyNonce); - var map = {}; + var map = new Map(); var i, tx, result, mempool; assert(cblock1.init()); @@ -399,16 +386,11 @@ describe('Block', function() { for (i = 0; i < block.txs.length; i++) { tx = block.txs[i]; - map[tx.hash('hex')] = tx; + map.set(tx.hash('hex'), { tx: tx }); } mempool = { - getSnapshot: function() { - return Object.keys(map); - }, - getTX: function(hash) { - return map[hash]; - } + map: map }; result = cblock1.fillMempool(false, mempool); @@ -426,29 +408,21 @@ describe('Block', function() { var block = Block.fromRaw(cmpct2block); var cblock1 = bip152.CompactBlock.fromRaw(cmpct2, 'hex'); var cblock2 = bip152.CompactBlock.fromBlock(block, false, cblock1.keyNonce); - var map = {}; - var i, tx, mid, keys, mempool, result, req, res; + var map = new Map(); + var i, tx, mempool, result, req, res; assert(cblock1.init()); assert.equal(cblock1.toRaw().toString('hex'), cmpct2); assert.equal(cblock2.toRaw().toString('hex'), cmpct2); - for (i = 0; i < block.txs.length; i++) { + for (i = 0; i < block.txs.length >>> 1; i++) { tx = block.txs[i]; - map[tx.hash('hex')] = tx; + map.set(tx.hash('hex'), { tx: tx }); } - mid = block.txs.length >>> 1; - keys = Object.keys(map).slice(0, mid); - mempool = { - getSnapshot: function() { - return keys; - }, - getTX: function(hash) { - return map[hash]; - } + map: map }; result = cblock1.fillMempool(false, mempool); diff --git a/test/node-test.js b/test/node-test.js index a7ad6408..0f2f3f70 100644 --- a/test/node-test.js +++ b/test/node-test.js @@ -594,7 +594,7 @@ describe('Node', function() { missing = await node.mempool.addTX(tx); assert(!missing || missing.length === 0); - assert.equal(node.mempool.totalTX, 1); + assert.equal(node.mempool.map.size, 1); }); it('should add lesser transaction to mempool', async function() { @@ -620,7 +620,7 @@ describe('Node', function() { missing = await node.mempool.addTX(tx); assert(!missing || missing.length === 0); - assert.equal(node.mempool.totalTX, 2); + assert.equal(node.mempool.map.size, 2); }); it('should get a block template', async function() {