itns-sidechain/lib/protocol/network.js

440 lines
8.9 KiB
JavaScript
Raw Normal View History

/*!
2016-08-23 23:26:50 -07:00
* network.js - network object for bcoin
2015-12-18 22:53:31 -08:00
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
2017-02-03 22:47:26 -08:00
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
2016-06-09 16:18:50 -07:00
* https://github.com/bcoin-org/bcoin
2015-12-18 22:53:31 -08:00
*/
2016-06-13 01:06:01 -07:00
'use strict';
2017-06-29 20:54:07 -07:00
const assert = require('assert');
2017-10-26 04:07:36 -07:00
const binary = require('../utils/binary');
2017-06-29 20:54:07 -07:00
const networks = require('./networks');
const TimeData = require('./timedata');
2016-08-23 23:26:50 -07:00
/**
2017-11-16 19:46:19 -08:00
* Network
2016-08-23 23:26:50 -07:00
* Represents a network.
2017-02-03 22:47:26 -08:00
* @alias module:protocol.Network
2016-08-23 23:26:50 -07:00
*/
2017-11-16 19:46:19 -08:00
class Network {
/**
* Create a network.
* @constructor
* @param {Object} options
*/
constructor(options) {
assert(!Network[options.type], 'Cannot create two networks.');
this.type = options.type;
this.seeds = options.seeds;
this.magic = options.magic;
this.port = options.port;
this.checkpointMap = options.checkpointMap;
this.lastCheckpoint = options.lastCheckpoint;
this.checkpoints = [];
this.halvingInterval = options.halvingInterval;
this.genesis = options.genesis;
this.genesisBlock = options.genesisBlock;
this.pow = options.pow;
2017-12-31 15:08:01 -08:00
this.cuckoo = options.cuckoo;
2017-11-16 19:46:19 -08:00
this.block = options.block;
this.activationThreshold = options.activationThreshold;
this.minerWindow = options.minerWindow;
this.deployments = options.deployments;
this.deploys = options.deploys;
2017-12-31 15:08:01 -08:00
this.unknownBits = 0;
2017-11-16 19:46:19 -08:00
this.keyPrefix = options.keyPrefix;
this.addressPrefix = options.addressPrefix;
this.requireStandard = options.requireStandard;
this.rpcPort = options.rpcPort;
this.walletPort = options.walletPort;
this.minRelay = options.minRelay;
this.feeRate = options.feeRate;
this.maxFeeRate = options.maxFeeRate;
this.selfConnect = options.selfConnect;
this.requestMempool = options.requestMempool;
this.time = new TimeData();
this.init();
}
2016-08-23 23:26:50 -07:00
2017-11-16 19:46:19 -08:00
/**
* Get a deployment by bit index.
* @param {Number} bit
* @returns {Object}
*/
2017-11-16 19:46:19 -08:00
init() {
let bits = 0;
2017-11-16 19:46:19 -08:00
for (const deployment of this.deploys)
bits |= 1 << deployment.bit;
2017-11-16 19:46:19 -08:00
this.unknownBits = ~bits >>> 0;
2017-11-16 19:46:19 -08:00
for (const key of Object.keys(this.checkpointMap)) {
const hash = this.checkpointMap[key];
const height = Number(key);
2016-11-23 15:18:38 -08:00
2017-11-16 19:46:19 -08:00
this.checkpoints.push({ hash, height });
}
2016-11-23 15:18:38 -08:00
2017-11-16 19:46:19 -08:00
this.checkpoints.sort(cmpNode);
}
2016-11-23 15:18:38 -08:00
2017-11-16 19:46:19 -08:00
/**
* Get a deployment by bit index.
* @param {Number} bit
* @returns {Object}
*/
2016-11-23 15:18:38 -08:00
2017-11-16 19:46:19 -08:00
byBit(bit) {
const index = binary.search(this.deploys, bit, cmpBit);
2017-01-21 03:01:18 -08:00
2017-11-16 19:46:19 -08:00
if (index === -1)
return null;
2017-01-21 03:01:18 -08:00
2017-11-16 19:46:19 -08:00
return this.deploys[index];
2017-01-21 03:01:18 -08:00
}
2017-11-16 19:46:19 -08:00
/**
* Get network adjusted time.
* @returns {Number}
*/
2016-11-23 15:18:38 -08:00
2017-11-16 19:46:19 -08:00
now() {
return this.time.now();
}
2016-11-23 15:18:38 -08:00
2017-11-16 19:46:19 -08:00
/**
* Get network adjusted time in milliseconds.
* @returns {Number}
*/
2016-11-28 16:52:30 -08:00
2017-11-16 19:46:19 -08:00
ms() {
return this.time.ms();
}
2016-11-28 16:52:30 -08:00
2017-11-16 19:46:19 -08:00
/**
* Create a network. Get existing network if possible.
* @param {NetworkType|Object} options
* @returns {Network}
*/
2017-03-06 18:25:06 -08:00
2017-11-16 19:46:19 -08:00
static create(options) {
if (typeof options === 'string')
options = networks[options];
2017-03-06 18:25:06 -08:00
2017-11-16 19:46:19 -08:00
assert(options, 'Unknown network.');
2017-11-16 19:46:19 -08:00
if (Network[options.type])
return Network[options.type];
2017-11-16 19:46:19 -08:00
const network = new Network(options);
2017-11-16 19:46:19 -08:00
Network[network.type] = network;
2016-04-17 15:58:12 -07:00
2017-11-16 19:46:19 -08:00
if (!Network.primary)
Network.primary = network;
2017-11-16 19:46:19 -08:00
return network;
}
2017-11-16 19:46:19 -08:00
/**
* Set the default network. This network will be used
* if nothing is passed as the `network` option for
* certain objects.
* @param {NetworkType} type - Network type.
* @returns {Network}
*/
static set(type) {
assert(typeof type === 'string', 'Bad network.');
Network.primary = Network.get(type);
Network.type = type;
return Network.primary;
}
2017-11-16 19:46:19 -08:00
/**
* Get a network with a string or a Network object.
* @param {NetworkType|Network} type - Network type.
* @returns {Network}
*/
2017-11-16 19:46:19 -08:00
static get(type) {
if (!type) {
assert(Network.primary, 'No default network.');
return Network.primary;
}
2017-11-16 19:46:19 -08:00
if (type instanceof Network)
return type;
2016-01-05 17:09:58 -08:00
2017-11-16 19:46:19 -08:00
if (typeof type === 'string')
return Network.create(type);
2017-11-16 19:46:19 -08:00
throw new Error('Unknown network.');
2016-08-23 23:26:50 -07:00
}
2017-11-16 19:46:19 -08:00
/**
* Get a network with a string or a Network object.
* @param {NetworkType|Network} type - Network type.
* @returns {Network}
*/
2016-02-16 20:55:00 -08:00
2017-11-16 19:46:19 -08:00
static ensure(type) {
if (!type) {
assert(Network.primary, 'No default network.');
return Network.primary;
}
2017-11-16 19:46:19 -08:00
if (type instanceof Network)
return type;
2017-11-16 19:46:19 -08:00
if (typeof type === 'string') {
if (networks[type])
return Network.create(type);
}
assert(Network.primary, 'No default network.');
2017-11-16 19:46:19 -08:00
return Network.primary;
}
2017-11-16 19:46:19 -08:00
/**
* Get a network by an associated comparator.
* @private
* @param {Object} value
* @param {Function} compare
* @param {Network|null} network
* @param {String} name
* @returns {Network}
*/
static by(value, compare, network, name) {
if (network) {
network = Network.get(network);
if (compare(network, value))
return network;
throw new Error(`Network mismatch for ${name}.`);
}
for (const type of networks.types) {
network = networks[type];
if (compare(network, value))
return Network.get(type);
}
throw new Error(`Network not found for ${name}.`);
}
2017-11-16 19:46:19 -08:00
/**
* Get a network by its magic number.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
2017-11-16 19:46:19 -08:00
static fromMagic(value, network) {
return Network.by(value, cmpMagic, network, 'magic number');
}
2017-11-16 19:46:19 -08:00
/**
* Get a network by its WIF prefix.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
2017-11-16 19:46:19 -08:00
static fromWIF(prefix, network) {
return Network.by(prefix, cmpWIF, network, 'WIF');
2017-05-13 21:35:58 -07:00
}
2017-11-16 19:46:19 -08:00
/**
* Get a network by its xpubkey prefix.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
2017-11-16 19:46:19 -08:00
static fromPublic(prefix, network) {
return Network.by(prefix, cmpPub, network, 'xpubkey');
}
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
/**
* Get a network by its xprivkey prefix.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
static fromPrivate(prefix, network) {
return Network.by(prefix, cmpPriv, network, 'xprivkey');
}
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
/**
* Get a network by its xpubkey base58 prefix.
* @param {String} prefix
* @param {Network?} network
* @returns {Network}
*/
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
static fromPublic58(prefix, network) {
return Network.by(prefix, cmpPub58, network, 'xpubkey');
}
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
/**
* Get a network by its xprivkey base58 prefix.
* @param {String} prefix
* @param {Network?} network
* @returns {Network}
*/
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
static fromPrivate58(prefix, network) {
return Network.by(prefix, cmpPriv58, network, 'xprivkey');
}
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
/**
* Get a network by its base58 address prefix.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
static fromAddress(prefix, network) {
return Network.by(prefix, cmpAddress, network, 'base58 address');
}
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
/**
* Get a network by its bech32 address prefix.
* @param {String} hrp
* @param {Network?} network
* @returns {Network}
*/
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
static fromBech32(hrp, network) {
return Network.by(hrp, cmpBech32, network, 'bech32 address');
}
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
/**
* Convert the network to a string.
* @returns {String}
*/
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
toString() {
return this.type;
}
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
/**
* Inspect the network.
* @returns {String}
*/
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
inspect() {
return `<Network: ${this.type}>`;
}
2017-11-16 19:46:19 -08:00
/**
* Test an object to see if it is a Network.
* @param {Object} obj
* @returns {Boolean}
*/
2017-05-13 21:35:58 -07:00
2017-11-16 19:46:19 -08:00
static isNetwork(obj) {
return obj instanceof Network;
}
}
2016-03-28 15:26:02 -07:00
2016-04-17 10:41:48 -07:00
/**
2017-11-16 19:46:19 -08:00
* Default network.
* @type {Network}
*/
2017-11-16 19:46:19 -08:00
Network.primary = null;
/**
2017-11-16 19:46:19 -08:00
* Default network type.
* @type {String}
2016-04-17 10:41:48 -07:00
*/
2017-11-16 19:46:19 -08:00
Network.type = null;
2016-01-16 23:48:18 -08:00
2017-11-16 19:46:19 -08:00
/*
* Networks (to avoid hash table mode).
2016-04-17 10:41:48 -07:00
*/
2017-11-16 19:46:19 -08:00
Network.main = null;
Network.testnet = null;
Network.regtest = null;
Network.segnet4 = null;
Network.simnet = null;
/*
* Set initial network.
*/
Network.set(process.env.BCOIN_NETWORK || 'main');
2016-11-23 15:18:38 -08:00
/*
* Helpers
*/
function cmpBit(a, b) {
return a.bit - b;
}
2017-01-21 03:01:18 -08:00
function cmpNode(a, b) {
return a.height - b.height;
}
2017-05-13 21:35:58 -07:00
function cmpMagic(network, magic) {
return network.magic === magic;
}
function cmpWIF(network, prefix) {
return network.keyPrefix.privkey === prefix;
}
function cmpPub(network, prefix) {
return network.keyPrefix.xpubkey === prefix;
}
function cmpPriv(network, prefix) {
return network.keyPrefix.xprivkey === prefix;
}
function cmpPub58(network, prefix) {
return network.keyPrefix.xpubkey58 === prefix;
}
function cmpPriv58(network, prefix) {
return network.keyPrefix.xprivkey58 === prefix;
}
function cmpAddress(network, prefix) {
2017-07-27 09:27:00 -07:00
const prefixes = network.addressPrefix;
2017-05-13 21:35:58 -07:00
switch (prefix) {
case prefixes.pubkeyhash:
case prefixes.scripthash:
case prefixes.witnesspubkeyhash:
case prefixes.witnessscripthash:
return true;
}
return false;
}
function cmpBech32(network, hrp) {
return network.addressPrefix.bech32 === hrp;
}
2016-04-17 10:41:48 -07:00
/*
2016-08-23 23:26:50 -07:00
* Expose
2016-04-17 10:41:48 -07:00
*/
2016-08-23 23:26:50 -07:00
module.exports = Network;