From 8ef82606e15e153222b8c4de5e943efa8ba2be11 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sun, 29 Oct 2017 08:25:32 -0700 Subject: [PATCH] bcoin: cleanup. remove rbt. --- lib/bcoin-browser.js | 114 ------ lib/bcoin.js | 115 ------ lib/utils/index.js | 2 +- lib/utils/rbt.js | 899 ------------------------------------------- 4 files changed, 1 insertion(+), 1129 deletions(-) delete mode 100644 lib/utils/rbt.js diff --git a/lib/bcoin-browser.js b/lib/bcoin-browser.js index 1d965c11..0b2538f4 100644 --- a/lib/bcoin-browser.js +++ b/lib/bcoin-browser.js @@ -15,111 +15,6 @@ * * @exports bcoin * @type {Object} - * - * @property {Function} bn - See {@url https://github.com/indutny/bn.js}. - * @property {Object} elliptic - See {@url https://github.com/indutny/elliptic}. - * - * @property {Object} bip70 - See {@link module:bip70}. - * - * @property {Object} blockchain - See {@link module:blockchain}. - * @property {Function} chain - See {@link module:blockchain.Chain}. - * @property {Function} chaindb - See {@link module:blockchain.ChainDB}. - * @property {Function} chainentry - See {@link module:blockchain.ChainEntry}. - * - * @property {Object} btc - * @property {Function} amount - * @property {Function} uri - * - * @property {Object} coins - * @property {Function} coinview - * - * @property {Object} crypto - * @property {Object} secp256k1 - * @property {Object} schnorr - * - * @property {Object} db - * @property {Object} ldb - * - * @property {Object} hd - * - * @property {Object} http - * @property {Object} rpc - * - * @property {Object} txmempool - * @property {Object} fees - * @property {Object} mempool - * @property {Object} mempoolentry - * - * @property {Object} mining - * @property {Object} miner - * @property {Object} minerblock - * - * @property {Object} net - * @property {Object} bip150 - * @property {Object} bip151 - * @property {Object} bip152 - * @property {Object} dns - * @property {Object} packets - * @property {Object} peer - * @property {Object} pool - * @property {Object} tcp - * - * @property {Object} node - * @property {Object} config - * @property {Object} fullnode - * @property {Object} logger - * @property {Object} spvnode - * - * @property {Object} primitives - * @property {Object} address - * @property {Object} block - * @property {Object} coin - * @property {Object} headers - * @property {Object} input - * @property {Object} invitem - * @property {Object} keyring - * @property {Object} merkleblock - * @property {Object} mtx - * @property {Object} netaddress - * @property {Object} outpoint - * @property {Object} output - * @property {Object} tx - * - * @property {Object} protocol - * @property {Object} consensus - * @property {Object} errors - * @property {Object} network - * @property {Object} networks - * @property {Object} policy - * @property {Object} timedata - * - * @property {Object} txscript - * @property {Object} opcodes - * @property {Object} program - * @property {Object} script - * @property {Object} sigcache - * @property {Object} stack - * @property {Object} witness - * - * @property {Object} utils - * @property {Object} base32 - * @property {Object} base58 - * @property {Object} bloom - * @property {Object} co - * @property {Object} encoding - * @property {Object} lock - * @property {Object} reader - * @property {Object} staticwriter - * @property {Object} util - * @property {Object} writer - * - * @property {Object} wallet - * @property {Object} path - * @property {Object} walletkey - * @property {Object} walletdb - * - * @property {Object} workers - * @property {Object} workerpool */ const bcoin = exports; @@ -164,13 +59,6 @@ bcoin.uri = require('./btc/uri'); bcoin.coins = require('./coins'); bcoin.coinview = require('./coins/coinview'); -// Crypto -bcoin.crypto = require('bcrypto'); - -// DB -bcoin.db = require('./db'); -bcoin.ldb = require('./db/ldb'); - // HD bcoin.hd = require('./hd'); @@ -198,9 +86,7 @@ bcoin.tcp = require('./net/tcp'); // Node bcoin.node = require('./node'); -bcoin.config = require('./node/config'); bcoin.fullnode = require('./node/fullnode'); -bcoin.logger = require('./node/logger'); bcoin.spvnode = require('./node/spvnode'); // Primitives diff --git a/lib/bcoin.js b/lib/bcoin.js index 96061c33..794ab546 100644 --- a/lib/bcoin.js +++ b/lib/bcoin.js @@ -17,111 +17,6 @@ * * @exports bcoin * @type {Object} - * - * @property {Function} bn - See {@url https://github.com/indutny/bn.js}. - * @property {Object} elliptic - See {@url https://github.com/indutny/elliptic}. - * - * @property {Object} bip70 - See {@link module:bip70}. - * - * @property {Object} blockchain - See {@link module:blockchain}. - * @property {Function} chain - See {@link module:blockchain.Chain}. - * @property {Function} chaindb - See {@link module:blockchain.ChainDB}. - * @property {Function} chainentry - See {@link module:blockchain.ChainEntry}. - * - * @property {Object} btc - * @property {Function} amount - * @property {Function} uri - * - * @property {Object} coins - * @property {Function} coinview - * - * @property {Object} crypto - * @property {Object} secp256k1 - * @property {Object} schnorr - * - * @property {Object} db - * @property {Object} ldb - * - * @property {Object} hd - * - * @property {Object} http - * @property {Object} rpc - * - * @property {Object} txmempool - * @property {Object} fees - * @property {Object} mempool - * @property {Object} mempoolentry - * - * @property {Object} mining - * @property {Object} miner - * @property {Object} minerblock - * - * @property {Object} net - * @property {Object} bip150 - * @property {Object} bip151 - * @property {Object} bip152 - * @property {Object} dns - * @property {Object} packets - * @property {Object} peer - * @property {Object} pool - * @property {Object} tcp - * - * @property {Object} node - * @property {Object} config - * @property {Object} fullnode - * @property {Object} logger - * @property {Object} spvnode - * - * @property {Object} primitives - * @property {Object} address - * @property {Object} block - * @property {Object} coin - * @property {Object} headers - * @property {Object} input - * @property {Object} invitem - * @property {Object} keyring - * @property {Object} merkleblock - * @property {Object} mtx - * @property {Object} netaddress - * @property {Object} outpoint - * @property {Object} output - * @property {Object} tx - * - * @property {Object} protocol - * @property {Object} consensus - * @property {Object} errors - * @property {Object} network - * @property {Object} networks - * @property {Object} policy - * @property {Object} timedata - * - * @property {Object} txscript - * @property {Object} opcodes - * @property {Object} program - * @property {Object} script - * @property {Object} sigcache - * @property {Object} stack - * @property {Object} witness - * - * @property {Object} utils - * @property {Object} base32 - * @property {Object} base58 - * @property {Object} bloom - * @property {Object} co - * @property {Object} encoding - * @property {Object} lock - * @property {Object} reader - * @property {Object} staticwriter - * @property {Object} util - * @property {Object} writer - * - * @property {Object} wallet - * @property {Object} path - * @property {Object} walletkey - * @property {Object} walletdb - * - * @property {Object} workers - * @property {Object} workerpool */ const bcoin = exports; @@ -163,7 +58,6 @@ bcoin.cache = function cache() { bcoin.btc; bcoin.coins; bcoin.crypto; - bcoin.db; bcoin.hd; bcoin.http; bcoin.txmempool; @@ -201,13 +95,6 @@ bcoin.define('uri', './btc/uri'); bcoin.define('coins', './coins'); bcoin.define('coinview', './coins/coinview'); -// Crypto -bcoin.define('crypto', 'bcrypto'); - -// DB -bcoin.define('db', './db'); -bcoin.define('ldb', './db/ldb'); - // HD bcoin.define('hd', './hd'); @@ -235,9 +122,7 @@ bcoin.define('tcp', './net/tcp'); // Node bcoin.define('node', './node'); -bcoin.define('config', './node/config'); bcoin.define('fullnode', './node/fullnode'); -bcoin.define('logger', './node/logger'); bcoin.define('spvnode', './node/spvnode'); // Primitives diff --git a/lib/utils/index.js b/lib/utils/index.js index 2d7277df..26425964 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -15,6 +15,7 @@ exports.AsyncObject = require('./asyncobject'); exports.base32 = require('./base32'); exports.base58 = require('./base58'); exports.bech32 = require('./bech32'); +exports.binary = require('./binary'); exports.Bloom = require('./bloom'); exports.co = require('./co'); exports.encoding = require('./encoding'); @@ -33,7 +34,6 @@ exports.murmur3 = require('./murmur3'); exports.nfkd = require('./nfkd'); exports.ProtoWriter = require('./protowriter'); exports.ProtoReader = require('./protoreader'); -exports.RBT = require('./rbt'); exports.BufferReader = require('./reader'); exports.RollingFilter = require('./rollingfilter'); exports.StaticWriter = require('./staticwriter'); diff --git a/lib/utils/rbt.js b/lib/utils/rbt.js deleted file mode 100644 index 17454395..00000000 --- a/lib/utils/rbt.js +++ /dev/null @@ -1,899 +0,0 @@ -/*! - * rbt.js - iterative red black tree for bcoin - * Copyright (c) 2016-2017, Christopher Jeffrey (MIT License). - * https://github.com/bcoin-org/bcoin - */ - -'use strict'; - -const assert = require('assert'); -const RED = 0; -const BLACK = 1; -let SENTINEL; - -/** - * An iterative red black tree. - * @alias module:utils.RBT - * @constructor - * @param {Function} compare - Comparator. - * @param {Boolean?} unique - */ - -function RBT(compare, unique) { - if (!(this instanceof RBT)) - return new RBT(compare, unique); - - assert(typeof compare === 'function'); - - this.root = SENTINEL; - this.compare = compare; - this.unique = unique || false; -} - -/** - * Clear the tree. - */ - -RBT.prototype.reset = function reset() { - this.root = SENTINEL; -}; - -/** - * Do a key lookup. - * @param {Buffer|String} key - * @returns {Buffer?} value - */ - -RBT.prototype.search = function search(key) { - let current = this.root; - - while (!current.isNull()) { - const cmp = this.compare(key, current.key); - - if (cmp === 0) - return current; - - if (cmp < 0) - current = current.left; - else - current = current.right; - } - - return null; -}; - -/** - * Insert a record. - * @param {Buffer|String} key - * @param {Buffer} value - */ - -RBT.prototype.insert = function insert(key, value) { - let current = this.root; - let left = false; - let parent; - - while (!current.isNull()) { - const cmp = this.compare(key, current.key); - - if (this.unique && cmp === 0) { - current.key = key; - current.value = value; - return current; - } - - parent = current; - - if (cmp < 0) { - left = true; - current = current.left; - } else { - left = false; - current = current.right; - } - } - - const node = new RBTNode(key, value); - - if (!parent) { - this.root = node; - this.insertFixup(node); - return node; - } - - node.parent = parent; - - if (left) - parent.left = node; - else - parent.right = node; - - this.insertFixup(node); - - return node; -}; - -/** - * Repaint necessary nodes after insertion. - * @private - * @param {RBTNode} x - */ - -RBT.prototype.insertFixup = function insertFixup(x) { - x.color = RED; - - while (x !== this.root && x.parent.color === RED) { - if (x.parent === x.parent.parent.left) { - const y = x.parent.parent.right; - if (!y.isNull() && y.color === RED) { - x.parent.color = BLACK; - y.color = BLACK; - x.parent.parent.color = RED; - x = x.parent.parent; - } else { - if (x === x.parent.right) { - x = x.parent; - this.rotl(x); - } - x.parent.color = BLACK; - x.parent.parent.color = RED; - this.rotr(x.parent.parent); - } - } else { - const y = x.parent.parent.left; - if (!y.isNull() && y.color === RED) { - x.parent.color = BLACK; - y.color = BLACK; - x.parent.parent.color = RED; - x = x.parent.parent; - } else { - if (x === x.parent.left) { - x = x.parent; - this.rotr(x); - } - x.parent.color = BLACK; - x.parent.parent.color = RED; - this.rotl(x.parent.parent); - } - } - } - - this.root.color = BLACK; -}; - -/** - * Remove a record. - * @param {Buffer|String} key - * @returns {Boolean} - */ - -RBT.prototype.remove = function remove(key) { - let current = this.root; - - while (!current.isNull()) { - const cmp = this.compare(key, current.key); - - if (cmp === 0) { - this.removeNode(current); - return current; - } - - if (cmp < 0) - current = current.left; - else - current = current.right; - } - - return null; -}; - -/** - * Remove a single node. - * @private - * @param {RBTNode} z - */ - -RBT.prototype.removeNode = function removeNode(z) { - let y = z; - - if (!z.left.isNull() && !z.right.isNull()) - y = this.successor(z); - - const x = y.left.isNull() ? y.right : y.left; - x.parent = y.parent; - - if (y.parent.isNull()) { - this.root = x; - } else { - if (y === y.parent.left) - y.parent.left = x; - else - y.parent.right = x; - } - - if (y !== z) { - z.key = y.key; - z.value = y.value; - } - - if (y.color === BLACK) - this.removeFixup(x); -}; - -/** - * Repaint necessary nodes after removal. - * @private - * @param {RBTNode} x - */ - -RBT.prototype.removeFixup = function removeFixup(x) { - while (x !== this.root && x.color === BLACK) { - if (x === x.parent.left) { - let w = x.parent.right; - - if (w.color === RED) { - w.color = BLACK; - x.parent.color = RED; - this.rotl(x.parent); - w = x.parent.right; - } - - if (w.left.color === BLACK && w.right.color === BLACK) { - w.color = RED; - x = x.parent; - } else { - if (w.right.color === BLACK) { - w.left.color = BLACK; - w.color = RED; - this.rotr(w); - w = x.parent.right; - } - w.color = x.parent.color; - x.parent.color = BLACK; - w.right.color = BLACK; - this.rotl(x.parent); - x = this.root; - } - } else { - let w = x.parent.left; - - if (w.color === RED) { - w.color = BLACK; - x.parent.color = RED; - this.rotr(x.parent); - w = x.parent.left; - } - - if (w.right.color === BLACK && w.left.color === BLACK) { - w.color = RED; - x = x.parent; - } else { - if (w.left.color === BLACK) { - w.right.color = BLACK; - w.color = RED; - this.rotl(w); - w = x.parent.left; - } - w.color = x.parent.color; - x.parent.color = BLACK; - w.left.color = BLACK; - this.rotr(x.parent); - x = this.root; - } - } - } - - x.color = BLACK; -}; - -/** - * Do a left rotate. - * @private - * @param {RBTNode} x - */ - -RBT.prototype.rotl = function rotl(x) { - const y = x.right; - - x.right = y.left; - - if (!y.left.isNull()) - y.left.parent = x; - - y.parent = x.parent; - - if (x.parent.isNull()) { - this.root = y; - } else { - if (x === x.parent.left) - x.parent.left = y; - else - x.parent.right = y; - } - - y.left = x; - x.parent = y; -}; - -/** - * Do a right rotate. - * @private - * @param {RBTNode} x - */ - -RBT.prototype.rotr = function rotr(x) { - const y = x.left; - - x.left = y.right; - - if (!y.right.isNull()) - y.right.parent = x; - - y.parent = x.parent; - - if (x.parent.isNull()) { - this.root = y; - } else { - if (x === x.parent.right) - x.parent.right = y; - else - x.parent.left = y; - } - - y.right = x; - x.parent = y; -}; - -/** - * Minimum subtree. - * @private - * @param {RBTNode} z - * @returns {RBTNode} - */ - -RBT.prototype.min = function min(z) { - if (z.isNull()) - return z; - - while (!z.left.isNull()) - z = z.left; - - return z; -}; - -/** - * Maximum subtree. - * @private - * @param {RBTNode} z - * @returns {RBTNode} - */ - -RBT.prototype.max = function max(z) { - if (z.isNull()) - return z; - - while (!z.right.isNull()) - z = z.right; - - return z; -}; - -/** - * Successor node. - * @private - * @param {RBTNode} x - * @returns {RBTNode} - */ - -RBT.prototype.successor = function successor(x) { - if (!x.right.isNull()) { - x = x.right; - - while (!x.left.isNull()) - x = x.left; - - return x; - } - - let y = x.parent; - while (!y.isNull() && x === y.right) { - x = y; - y = y.parent; - } - - return y; -}; - -/** - * Predecessor node. - * @private - * @param {RBTNode} x - * @returns {RBTNode} - */ - -RBT.prototype.predecessor = function predecessor(x) { - if (!x.left.isNull()) { - x = x.left; - - while (!x.right.isNull()) - x = x.right; - - return x; - } - - let y = x.parent; - while (!y.isNull() && x === y.left) { - x = y; - y = y.parent; - } - - return y; -}; - -/** - * Take a snapshot and return - * a cloned root node (iterative). - * @returns {RBTNode} - */ - -RBT.prototype.clone = function clone() { - if (this.root.isNull()) - return SENTINEL; - - const stack = []; - - let current = this.root; - let left = true; - let parent, snapshot; - - for (;;) { - if (!current.isNull()) { - const copy = current.clone(); - - if (parent) - copy.parent = parent; - - if (left) { - if (parent) - parent.left = copy; - else - snapshot = copy; - } else { - if (parent) - parent.right = copy; - else - snapshot = copy; - } - - stack.push(copy); - parent = copy; - left = true; - current = current.left; - continue; - } - - if (stack.length === 0) - break; - - current = stack.pop(); - parent = current; - left = false; - current = current.right; - } - - assert(snapshot); - - return snapshot; -}; - -/** - * Take a snapshot and return - * a cloned root node (recursive). - * @returns {RBTNode} - */ - -RBT.prototype.snapshot = function snapshot() { - if (this.root.isNull()) - return SENTINEL; - - const node = this.root.clone(); - - copyLeft(node, node.left); - copyRight(node, node.right); - - return node; -}; - -/** - * Create an iterator. - * @param {RBTNode?} snapshot - * @returns {Iterator} - */ - -RBT.prototype.iterator = function iterator(snapshot) { - return new Iterator(this, snapshot || this.root); -}; - -/** - * Traverse between a range of keys and collect records. - * @param {Buffer} min - * @param {Buffer} max - * @returns {RBTNode[]} Records. - */ - -RBT.prototype.range = function range(min, max) { - const iter = this.iterator(); - const items = []; - - if (min) - iter.seekMin(min); - else - iter.seekFirst(); - - while (iter.next()) { - if (max && iter.compare(max) > 0) - break; - - items.push(iter.data()); - } - - return items; -}; - -/** - * Iterator - * @constructor - * @ignore - * @param {RBT} tree - * @param {RBTNode} snapshot - * @property {RBT} tree - * @property {RBTNode} current - * @property {Object} key - * @property {Object} value - */ - -function Iterator(tree, snapshot) { - this.tree = tree; - this.root = snapshot; - this.current = snapshot; - this.key = null; - this.value = null; -} - -/** - * Compare keys using tree's comparator. - * @param {Object} key - */ - -Iterator.prototype.compare = function compare(key) { - assert(this.key != null, 'No key.'); - return this.tree.compare(this.key, key); -}; - -/** - * Test whether current node is valid. - */ - -Iterator.prototype.valid = function valid() { - return !this.current.isNull(); -}; - -/** - * Seek to the root. - */ - -Iterator.prototype.reset = function reset() { - this.current = this.root; - this.key = null; - this.value = null; -}; - -/** - * Seek to the start of the tree. - */ - -Iterator.prototype.seekFirst = function seekFirst() { - this.current = this.tree.min(this.root); - this.key = this.current.key; - this.value = this.current.value; -}; - -/** - * Seek to the end of the tree. - */ - -Iterator.prototype.seekLast = function seekLast() { - this.current = this.tree.max(this.root); - this.key = this.current.key; - this.value = this.current.value; -}; - -/** - * Seek to a key from the current node (gte). - * @param {String} key - */ - -Iterator.prototype.seek = function seek(key) { - return this.seekMin(key); -}; - -/** - * Seek to a key from the current node (gte). - * @param {String} key - */ - -Iterator.prototype.seekMin = function seekMin(key) { - assert(key != null, 'No key passed to seek.'); - - let root = this.current; - let current = SENTINEL; - - while (!root.isNull()) { - const cmp = this.tree.compare(root.key, key); - - if (cmp === 0) { - current = root; - break; - } - - if (cmp > 0) { - current = root; - root = root.left; - } else { - root = root.right; - } - } - - this.current = current; - this.key = current.key; - this.value = current.value; -}; - -/** - * Seek to a key from the current node (lte). - * @param {String} key - */ - -Iterator.prototype.seekMax = function seekMax(key) { - assert(key != null, 'No key passed to seek.'); - - let root = this.current; - let current = SENTINEL; - - while (!root.isNull()) { - const cmp = this.tree.compare(root.key, key); - - if (cmp === 0) { - current = root; - break; - } - - if (cmp < 0) { - current = root; - root = root.right; - } else { - root = root.left; - } - } - - this.current = current; - this.key = current.key; - this.value = current.value; -}; - -/** - * Seek to previous node. - * @param {String} key - */ - -Iterator.prototype.prev = function prev() { - if (this.current.isNull()) { - this.key = null; - this.value = null; - return false; - } - - this.key = this.current.key; - this.value = this.current.value; - this.current = this.tree.predecessor(this.current); - - return true; -}; - -/** - * Seek to next node. - * @returns {Boolean} - */ - -Iterator.prototype.next = function next() { - if (this.current.isNull()) { - this.key = null; - this.value = null; - return false; - } - - this.key = this.current.key; - this.value = this.current.value; - this.current = this.tree.successor(this.current); - - return true; -}; - -/** - * Return the current key/value pair. - * @returns {RBTData} - */ - -Iterator.prototype.data = function data() { - assert(this.key != null, 'No data available.'); - return new RBTData(this.key, this.value); -}; - -/** - * RBT Node - * @constructor - * @ignore - * @private - * @param {Buffer} key - * @param {Buffer} value - * @property {Buffer} key - * @property {Buffer} value - * @property {Number} color - * @property {RBTNode|RBTSentinel} parent - * @property {RBTNode|RBTSentinel} left - * @property {RBTNode|RBTSentinel} right - */ - -function RBTNode(key, value) { - this.key = key; - this.value = value; - this.color = RED; - this.parent = SENTINEL; - this.left = SENTINEL; - this.right = SENTINEL; -} - -/** - * Clone the node. - * @returns {RBTNode} - */ - -RBTNode.prototype.clone = function clone() { - const node = new RBTNode(this.key, this.value); - node.color = this.color; - node.parent = this.parent; - node.left = this.left; - node.right = this.right; - return node; -}; - -/** - * Clone the node (key/value only). - * @returns {RBTData} - */ - -RBTNode.prototype.copy = function copy() { - return new RBTData(this.key, this.value); -}; - -/** - * Inspect the rbt node. - * @returns {Object} - */ - -RBTNode.prototype.inspect = function inspect() { - return { - key: this.key, - value: this.value, - color: this.color === RED ? 'red' : 'black', - left: this.left, - right: this.right - }; -}; - -/** - * Test whether the node is a leaf. - * Always returns false. - * @returns {Boolean} - */ - -RBTNode.prototype.isNull = function isNull() { - return false; -}; - -/** - * RBT Sentinel Node - * @constructor - * @ignore - * @property {null} key - * @property {null} value - * @property {Number} [color=BLACK] - * @property {null} parent - * @property {null} left - * @property {null} right - */ - -function RBTSentinel() { - this.key = null; - this.value = null; - this.color = BLACK; - this.parent = null; - this.left = null; - this.right = null; -} - -/** - * Inspect the rbt node. - * @returns {String} - */ - -RBTSentinel.prototype.inspect = function inspect() { - return 'NIL'; -}; - -/** - * Test whether the node is a leaf. - * Always returns true. - * @returns {Boolean} - */ - -RBTSentinel.prototype.isNull = function isNull() { - return true; -}; - -/** - * RBT key/value pair - * @constructor - * @ignore - * @param {Buffer} key - * @param {Buffer} value - * @property {Buffer} key - * @property {Buffer} value - */ - -function RBTData(key, value) { - this.key = key; - this.value = value; -} - -/** - * Inspect the rbt data. - * @returns {Object} - */ - -RBTData.prototype.inspect = function inspect() { - return { - key: this.key, - value: this.value - }; -}; - -/* - * Helpers - */ - -SENTINEL = new RBTSentinel(); - -function copyLeft(parent, node) { - if (!node.isNull()) { - parent.left = node.clone(); - parent.left.parent = parent; - copyLeft(parent.left, node.left); - copyRight(parent.left, node.right); - } -} - -function copyRight(parent, node) { - if (!node.isNull()) { - parent.right = node.clone(); - parent.right.parent = parent; - copyLeft(parent.right, node.left); - copyRight(parent.right, node.right); - } -} - -/* - * Expose - */ - -module.exports = RBT;