hip2-server/build/hip2-server.js
2022-03-06 11:38:41 -05:00

32134 lines
683 KiB
JavaScript

/*!
* hip2-server@1.0.0
* Copyright (c) 2022, Matthew Zipkin (MIT)
* https://github.com/pinheadmz/hip2-server#readme
*/
var __node_modules__ = [
[/* 0 */ 'hip2-server', '/src/derive.js', function(exports, module, __filename, __dirname, __meta) {
'use strict';
const HDPublicKey = __node_require__(1 /* 'hsd/lib/hd/public' */);
const Address = __node_require__(55 /* 'hsd/lib/primitives/address' */);
const fs = require('fs');
const path = require('path');
const http = require('http');
const MAX_INDEX = 0x7fffffff;
if (process.argv.length < 3)
throw new Error('Usage: node build/hip2-server.js <PORT>');
const port = process.argv[2];
const xpubFile = path.join(__dirname, '..', 'conf', 'xpub');
let xpub;
try {
xpub = fs.readFileSync(xpubFile, 'ascii');
} catch (e) {
throw new Error('xpub file missing');
}
xpub = xpub.split('\n')[0];
if (xpub === 'xpub6DBMpym6PM3qe7Ug7BwG6zo7dinMMjpk8nmb73czsjkzPTzfQ1d5ZvqDea4uNmMVv1Y9DT6v17GuDL1x2km9FQuKqWMdnrDfRiDNrG1nTMr')
throw new Error('Example xpub must not be used! Repalce with your own account xpub.');
const acct = HDPublicKey.fromBase58(xpub);
const recv = acct.derive(0);
function addr() {
const indexFile = path.join(__dirname, '..', 'log', 'hip2-index');
let index = 0;
try {
index = parseInt(fs.readFileSync(indexFile));
} catch (e) {
;
}
fs.writeFileSync(indexFile, index + 1);
// Wow, used all our non-hardened addresses!
// Don't roll over the saved index (that way the user knows this has happened)
// but start over the address space and reuse addresses starting again at 0.
if (index >= MAX_INDEX)
index -= MAX_INDEX;
const pk = recv.derive(index);
const addr = Address.fromPubkey(pk.publicKey).toString();
return addr;
}
const requestListener = function (req, res) {
res.writeHead(200);
res.end(addr());
};
const server = http.createServer(requestListener);
server.listen({port});
}],
[/* 1 */ 'hsd', '/lib/hd/public.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* public.js - hd public keys for hsd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
'use strict';
const assert = __node_require__(2 /* 'bsert' */);
const bio = __node_require__(3 /* 'bufio' */);
const base58 = __node_require__(12 /* 'bcrypto/lib/encoding/base58' */);
const sha512 = __node_require__(15 /* 'bcrypto/lib/sha512' */);
const hash160 = __node_require__(18 /* 'bcrypto/lib/hash160' */);
const hash256 = __node_require__(22 /* 'bcrypto/lib/hash256' */);
const cleanse = __node_require__(24 /* 'bcrypto/lib/cleanse' */);
const secp256k1 = __node_require__(28 /* 'bcrypto/lib/secp256k1' */);
const Network = __node_require__(44 /* '../protocol/network' */);
const consensus = __node_require__(51 /* '../protocol/consensus' */);
const common = __node_require__(52 /* './common' */);
/**
* HDPublicKey
* @alias module:hd.PublicKey
* @property {Number} depth
* @property {Number} parentFingerPrint
* @property {Number} childIndex
* @property {Buffer} chainCode
* @property {Buffer} publicKey
*/
class HDPublicKey extends bio.Struct {
/**
* Create an HD public key.
* @constructor
* @param {Object|Base58String} options
* @param {Base58String?} options.xkey - Serialized base58 key.
* @param {Number?} options.depth
* @param {Number?} options.parentFingerPrint
* @param {Number?} options.childIndex
* @param {Buffer?} options.chainCode
* @param {Buffer?} options.publicKey
*/
constructor(options) {
super();
this.depth = 0;
this.parentFingerPrint = 0;
this.childIndex = 0;
this.chainCode = consensus.ZERO_HASH;
this.publicKey = common.ZERO_KEY;
this.fingerPrint = -1;
if (options)
this.fromOptions(options);
}
/**
* Inject properties from options object.
* @private
* @param {Object} options
*/
fromOptions(options) {
assert(options, 'No options for HDPublicKey');
assert((options.depth & 0xff) === options.depth);
assert((options.parentFingerPrint >>> 0) === options.parentFingerPrint);
assert((options.childIndex >>> 0) === options.childIndex);
assert(Buffer.isBuffer(options.chainCode));
assert(Buffer.isBuffer(options.publicKey));
this.depth = options.depth;
this.parentFingerPrint = options.parentFingerPrint;
this.childIndex = options.childIndex;
this.chainCode = options.chainCode;
this.publicKey = options.publicKey;
return this;
}
/**
* Get HD public key (self).
* @returns {HDPublicKey}
*/
toPublic() {
return this;
}
/**
* Get cached base58 xprivkey (always null here).
* @returns {null}
*/
xprivkey(network) {
return null;
}
/**
* Get cached base58 xpubkey.
* @returns {Base58String}
*/
xpubkey(network) {
return this.toBase58(network);
}
/**
* Destroy the key (zeroes chain code and pubkey).
*/
destroy() {
this.depth = 0;
this.childIndex = 0;
this.parentFingerPrint = 0;
cleanse(this.chainCode);
cleanse(this.publicKey);
this.fingerPrint = -1;
}
/**
* Derive a child key.
* @param {Number} index - Derivation index.
* @param {Boolean?} hardened - Whether the derivation
* should be hardened (throws if true).
* @returns {HDPrivateKey}
* @throws on `hardened`
*/
derive(index, hardened) {
assert(typeof index === 'number');
if ((index >>> 0) !== index)
throw new Error('Index out of range.');
if ((index & common.HARDENED) || hardened)
throw new Error('Cannot derive hardened.');
if (this.depth >= 0xff)
throw new Error('Depth too high.');
const id = this.getID(index);
const cache = common.cache.get(id);
if (cache)
return cache;
const bw = bio.pool(37);
bw.writeBytes(this.publicKey);
bw.writeU32BE(index);
const data = bw.render();
const hash = sha512.mac(data, this.chainCode);
const left = hash.slice(0, 32);
const right = hash.slice(32, 64);
let key;
try {
key = secp256k1.publicKeyTweakAdd(this.publicKey, left, true);
} catch (e) {
return this.derive(index + 1);
}
if (this.fingerPrint === -1) {
const fp = hash160.digest(this.publicKey);
this.fingerPrint = fp.readUInt32BE(0, true);
}
const child = new this.constructor();
child.depth = this.depth + 1;
child.parentFingerPrint = this.fingerPrint;
child.childIndex = index;
child.chainCode = right;
child.publicKey = key;
common.cache.set(id, child);
return child;
}
/**
* Unique HD key ID.
* @private
* @param {Number} index
* @returns {String}
*/
getID(index) {
return 'b' + this.publicKey.toString('hex') + index;
}
/**
* Derive a BIP44 account key (does not derive, only ensures account key).
* @method
* @param {Number} purpose
* @param {Number} type
* @param {Number} account
* @returns {HDPublicKey}
* @throws Error if key is not already an account key.
*/
deriveAccount(purpose, type, account) {
assert((purpose >>> 0) === purpose);
assert((type >>> 0) === type);
assert((account >>> 0) === account);
assert(this.isAccount(account), 'Cannot derive account index.');
return this;
}
/**
* Test whether the key is a master key.
* @method
* @returns {Boolean}
*/
isMaster() {
return common.isMaster(this);
}
/**
* Test whether the key is (most likely) a BIP44 account key.
* @method
* @param {Number?} account
* @returns {Boolean}
*/
isAccount(account) {
return common.isAccount(this, account);
}
/**
* Test whether a string is a valid path.
* @param {String} path
* @param {Boolean?} hardened
* @returns {Boolean}
*/
static isValidPath(path) {
try {
common.parsePath(path, false);
return true;
} catch (e) {
return false;
}
}
/**
* Derive a key from a derivation path.
* @param {String} path
* @returns {HDPublicKey}
* @throws Error if `path` is not a valid path.
* @throws Error if hardened.
*/
derivePath(path) {
const indexes = common.parsePath(path, false);
let key = this;
for (const index of indexes)
key = key.derive(index);
return key;
}
/**
* Compare a key against an object.
* @param {Object} obj
* @returns {Boolean}
*/
equals(obj) {
assert(HDPublicKey.isHDPublicKey(obj));
return this.depth === obj.depth
&& this.parentFingerPrint === obj.parentFingerPrint
&& this.childIndex === obj.childIndex
&& this.chainCode.equals(obj.chainCode)
&& this.publicKey.equals(obj.publicKey);
}
/**
* Compare a key against an object.
* @param {Object} obj
* @returns {Boolean}
*/
compare(key) {
assert(HDPublicKey.isHDPublicKey(key));
let cmp = this.depth - key.depth;
if (cmp !== 0)
return cmp;
cmp = this.parentFingerPrint - key.parentFingerPrint;
if (cmp !== 0)
return cmp;
cmp = this.childIndex - key.childIndex;
if (cmp !== 0)
return cmp;
cmp = this.chainCode.compare(key.chainCode);
if (cmp !== 0)
return cmp;
cmp = this.publicKey.compare(key.publicKey);
if (cmp !== 0)
return cmp;
return 0;
}
/**
* Convert key to a more json-friendly object.
* @returns {Object}
*/
getJSON(network) {
return {
xpubkey: this.xpubkey(network)
};
}
/**
* Inject properties from json object.
* @private
* @param {Object} json
* @param {Network?} network
*/
fromJSON(json, network) {
assert(json.xpubkey, 'Could not handle HD key JSON.');
this.fromBase58(json.xpubkey, network);
return this;
}
/**
* Test whether an object is in the form of a base58 xpubkey.
* @param {String} data
* @param {(Network|NetworkType)?} network
* @returns {Boolean}
*/
static isBase58(data, network) {
if (typeof data !== 'string')
return false;
if (data.length < 4)
return false;
const prefix = data.substring(0, 4);
try {
Network.fromPublic58(prefix, network);
return true;
} catch (e) {
return false;
}
}
/**
* Test whether a buffer has a valid network prefix.
* @param {Buffer} data
* @param {(Network|NetworkType)?} network
* @returns {NetworkType}
*/
static isRaw(data, network) {
if (!Buffer.isBuffer(data))
return false;
if (data.length < 4)
return false;
const version = data.readUInt32BE(0, true);
try {
Network.fromPublic(version, network);
return true;
} catch (e) {
return false;
}
}
/**
* Inject properties from a base58 key.
* @private
* @param {Base58String} xkey
* @param {Network?} network
*/
fromBase58(xkey, network) {
assert(typeof xkey === 'string');
return this.decode(base58.decode(xkey), network);
}
/**
* Inject properties from serialized data.
* @private
* @param {BufferReader} br
* @param {(Network|NetworkType)?} network
*/
read(br, network) {
const version = br.readU32BE();
Network.fromPublic(version, network);
this.depth = br.readU8();
this.parentFingerPrint = br.readU32BE();
this.childIndex = br.readU32BE();
this.chainCode = br.readBytes(32);
this.publicKey = br.readBytes(33);
br.verifyChecksum(hash256.digest);
return this;
}
/**
* Serialize key data to base58 extended key.
* @param {(Network|NetworkType)?} network
* @returns {Base58String}
*/
toBase58(network) {
return base58.encode(this.encode(network));
}
/**
* Write the key to a buffer writer.
* @param {BufferWriter} bw
* @param {(Network|NetworkType)?} network
*/
write(bw, network) {
network = Network.get(network);
bw.writeU32BE(network.keyPrefix.xpubkey);
bw.writeU8(this.depth);
bw.writeU32BE(this.parentFingerPrint);
bw.writeU32BE(this.childIndex);
bw.writeBytes(this.chainCode);
bw.writeBytes(this.publicKey);
bw.writeChecksum(hash256.digest);
return bw;
}
/**
* Calculate serialization size.
* @returns {Number}
*/
getSize() {
return 82;
}
/**
* Instantiate an HD public key from a base58 string.
* @param {Base58String} xkey
* @param {Network?} network
* @returns {HDPublicKey}
*/
static fromBase58(xkey, network) {
return new this().fromBase58(xkey, network);
}
/**
* Test whether an object is a HDPublicKey.
* @param {Object} obj
* @returns {Boolean}
*/
static isHDPublicKey(obj) {
return obj instanceof HDPublicKey;
}
}
/*
* Expose
*/
module.exports = HDPublicKey;
}],
[/* 2 */ 'bsert', '/lib/assert.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* assert.js - assertions for javascript
* Copyright (c) 2018, Christopher Jeffrey (MIT License).
* https://github.com/chjj/bsert
*/
'use strict';
/**
* AssertionError
*/
class AssertionError extends Error {
constructor(options) {
if (typeof options === 'string')
options = { message: options };
if (options === null || typeof options !== 'object')
options = {};
let message = null;
let operator = 'fail';
let generatedMessage = Boolean(options.generatedMessage);
if (options.message != null)
message = toString(options.message);
if (typeof options.operator === 'string')
operator = options.operator;
if (message == null) {
if (operator === 'fail') {
message = 'Assertion failed.';
} else {
const a = stringify(options.actual);
const b = stringify(options.expected);
message = `${a} ${operator} ${b}`;
}
generatedMessage = true;
}
super(message);
let start = this.constructor;
if (typeof options.stackStartFunction === 'function')
start = options.stackStartFunction;
else if (typeof options.stackStartFn === 'function')
start = options.stackStartFn;
this.type = 'AssertionError';
this.name = 'AssertionError [ERR_ASSERTION]';
this.code = 'ERR_ASSERTION';
this.generatedMessage = generatedMessage;
this.actual = options.actual;
this.expected = options.expected;
this.operator = operator;
if (Error.captureStackTrace)
Error.captureStackTrace(this, start);
}
}
/*
* Assert
*/
function assert(value, message) {
if (!value) {
let generatedMessage = false;
if (arguments.length === 0) {
message = 'No value argument passed to `assert()`.';
generatedMessage = true;
} else if (message == null) {
message = 'Assertion failed.';
generatedMessage = true;
} else if (isError(message)) {
throw message;
}
throw new AssertionError({
message,
actual: value,
expected: true,
operator: '==',
generatedMessage,
stackStartFn: assert
});
}
}
function equal(actual, expected, message) {
if (!Object.is(actual, expected)) {
if (isError(message))
throw message;
throw new AssertionError({
message,
actual,
expected,
operator: 'strictEqual',
stackStartFn: equal
});
}
}
function notEqual(actual, expected, message) {
if (Object.is(actual, expected)) {
if (isError(message))
throw message;
throw new AssertionError({
message,
actual,
expected,
operator: 'notStrictEqual',
stackStartFn: notEqual
});
}
}
function fail(message) {
let generatedMessage = false;
if (isError(message))
throw message;
if (message == null) {
message = 'Assertion failed.';
generatedMessage = true;
}
throw new AssertionError({
message,
actual: false,
expected: true,
operator: 'fail',
generatedMessage,
stackStartFn: fail
});
}
function throws(func, expected, message) {
if (typeof expected === 'string') {
message = expected;
expected = undefined;
}
let thrown = false;
let err = null;
enforce(typeof func === 'function', 'func', 'function');
try {
func();
} catch (e) {
thrown = true;
err = e;
}
if (!thrown) {
let generatedMessage = false;
if (message == null) {
message = 'Missing expected exception.';
generatedMessage = true;
}
throw new AssertionError({
message,
actual: undefined,
expected,
operator: 'throws',
generatedMessage,
stackStartFn: throws
});
}
if (!testError(err, expected, message, throws))
throw err;
}
function doesNotThrow(func, expected, message) {
if (typeof expected === 'string') {
message = expected;
expected = undefined;
}
let thrown = false;
let err = null;
enforce(typeof func === 'function', 'func', 'function');
try {
func();
} catch (e) {
thrown = true;
err = e;
}
if (!thrown)
return;
if (testError(err, expected, message, doesNotThrow)) {
let generatedMessage = false;
if (message == null) {
message = 'Got unwanted exception.';
generatedMessage = true;
}
throw new AssertionError({
message,
actual: err,
expected,
operator: 'doesNotThrow',
generatedMessage,
stackStartFn: doesNotThrow
});
}
throw err;
}
async function rejects(func, expected, message) {
if (typeof expected === 'string') {
message = expected;
expected = undefined;
}
let thrown = false;
let err = null;
if (typeof func !== 'function')
enforce(isPromise(func), 'func', 'promise');
try {
if (isPromise(func))
await func;
else
await func();
} catch (e) {
thrown = true;
err = e;
}
if (!thrown) {
let generatedMessage = false;
if (message == null) {
message = 'Missing expected rejection.';
generatedMessage = true;
}
throw new AssertionError({
message,
actual: undefined,
expected,
operator: 'rejects',
generatedMessage,
stackStartFn: rejects
});
}
if (!testError(err, expected, message, rejects))
throw err;
}
async function doesNotReject(func, expected, message) {
if (typeof expected === 'string') {
message = expected;
expected = undefined;
}
let thrown = false;
let err = null;
if (typeof func !== 'function')
enforce(isPromise(func), 'func', 'promise');
try {
if (isPromise(func))
await func;
else
await func();
} catch (e) {
thrown = true;
err = e;
}
if (!thrown)
return;
if (testError(err, expected, message, doesNotReject)) {
let generatedMessage = false;
if (message == null) {
message = 'Got unwanted rejection.';
generatedMessage = true;
}
throw new AssertionError({
message,
actual: undefined,
expected,
operator: 'doesNotReject',
generatedMessage,
stackStartFn: doesNotReject
});
}
throw err;
}
function ifError(err) {
if (err != null) {
let message = 'ifError got unwanted exception: ';
if (typeof err === 'object' && typeof err.message === 'string') {
if (err.message.length === 0 && err.constructor)
message += err.constructor.name;
else
message += err.message;
} else {
message += stringify(err);
}
throw new AssertionError({
message,
actual: err,
expected: null,
operator: 'ifError',
generatedMessage: true,
stackStartFn: ifError
});
}
}
function deepEqual(actual, expected, message) {
if (!isDeepEqual(actual, expected, false)) {
if (isError(message))
throw message;
throw new AssertionError({
message,
actual,
expected,
operator: 'deepStrictEqual',
stackStartFn: deepEqual
});
}
}
function notDeepEqual(actual, expected, message) {
if (isDeepEqual(actual, expected, true)) {
if (isError(message))
throw message;
throw new AssertionError({
message,
actual,
expected,
operator: 'notDeepStrictEqual',
stackStartFn: notDeepEqual
});
}
}
function bufferEqual(actual, expected, enc, message) {
if (!isEncoding(enc)) {
message = enc;
enc = null;
}
if (enc == null)
enc = 'hex';
expected = bufferize(actual, expected, enc);
enforce(isBuffer(actual), 'actual', 'buffer');
enforce(isBuffer(expected), 'expected', 'buffer');
if (actual !== expected && !actual.equals(expected)) {
if (isError(message))
throw message;
throw new AssertionError({
message,
actual: actual.toString(enc),
expected: expected.toString(enc),
operator: 'bufferEqual',
stackStartFn: bufferEqual
});
}
}
function notBufferEqual(actual, expected, enc, message) {
if (!isEncoding(enc)) {
message = enc;
enc = null;
}
if (enc == null)
enc = 'hex';
expected = bufferize(actual, expected, enc);
enforce(isBuffer(actual), 'actual', 'buffer');
enforce(isBuffer(expected), 'expected', 'buffer');
if (actual === expected || actual.equals(expected)) {
if (isError(message))
throw message;
throw new AssertionError({
message,
actual: actual.toString(enc),
expected: expected.toString(enc),
operator: 'notBufferEqual',
stackStartFn: notBufferEqual
});
}
}
function enforce(value, name, type) {
if (!value) {
let msg;
if (name == null) {
msg = 'Invalid type for parameter.';
} else {
if (type == null)
msg = `Invalid type for "${name}".`;
else
msg = `"${name}" must be a(n) ${type}.`;
}
const err = new TypeError(msg);
if (Error.captureStackTrace)
Error.captureStackTrace(err, enforce);
throw err;
}
}
function range(value, name) {
if (!value) {
const msg = name != null
? `"${name}" is out of range.`
: 'Parameter is out of range.';
const err = new RangeError(msg);
if (Error.captureStackTrace)
Error.captureStackTrace(err, range);
throw err;
}
}
/*
* Stringification
*/
function stringify(value) {
switch (typeof value) {
case 'undefined':
return 'undefined';
case 'object':
if (value === null)
return 'null';
return `[${objectName(value)}]`;
case 'boolean':
return `${value}`;
case 'number':
return `${value}`;
case 'string':
if (value.length > 80)
value = `${value.substring(0, 77)}...`;
return JSON.stringify(value);
case 'symbol':
return tryString(value);
case 'function':
return `[${funcName(value)}]`;
case 'bigint':
return `${value}n`;
default:
return `[${typeof value}]`;
}
}
function toString(value) {
if (typeof value === 'string')
return value;
if (isError(value))
return tryString(value);
return stringify(value);
}
function tryString(value) {
try {
return String(value);
} catch (e) {
return 'Object';
}
}
/*
* Error Testing
*/
function testError(err, expected, message, func) {
if (expected == null)
return true;
if (isRegExp(expected))
return expected.test(err);
if (typeof expected !== 'function') {
if (func === doesNotThrow || func === doesNotReject)
throw new TypeError('"expected" must not be an object.');
if (typeof expected !== 'object')
throw new TypeError('"expected" must be an object.');
let generatedMessage = false;
if (message == null) {
const name = func === rejects ? 'rejection' : 'exception';
message = `Missing expected ${name}.`;
generatedMessage = true;
}
if (err == null || typeof err !== 'object') {
throw new AssertionError({
actual: err,
expected,
message,
operator: func.name,
generatedMessage,
stackStartFn: func
});
}
const keys = Object.keys(expected);
if (isError(expected))
keys.push('name', 'message');
if (keys.length === 0)
throw new TypeError('"expected" may not be an empty object.');
for (const key of keys) {
const expect = expected[key];
const value = err[key];
if (typeof value === 'string'
&& isRegExp(expect)
&& expect.test(value)) {
continue;
}
if ((key in err) && isDeepEqual(value, expect, false))
continue;
throw new AssertionError({
actual: err,
expected: expected,
message,
operator: func.name,
generatedMessage,
stackStartFn: func
});
}
return true;
}
if (expected.prototype !== undefined && (err instanceof expected))
return true;
if (Error.isPrototypeOf(expected))
return false;
return expected.call({}, err) === true;
}
/*
* Comparisons
*/
function isDeepEqual(x, y, fail) {
try {
return compare(x, y, null);
} catch (e) {
return fail;
}
}
function compare(a, b, cache) {
// Primitives.
if (Object.is(a, b))
return true;
if (!isObject(a) || !isObject(b))
return false;
// Semi-primitives.
if (objectString(a) !== objectString(b))
return false;
if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
return false;
if (isBuffer(a) && isBuffer(b))
return a.equals(b);
if (isDate(a))
return Object.is(a.getTime(), b.getTime());
if (isRegExp(a)) {
return a.source === b.source
&& a.global === b.global
&& a.multiline === b.multiline
&& a.lastIndex === b.lastIndex
&& a.ignoreCase === b.ignoreCase;
}
if (isError(a)) {
if (a.message !== b.message)
return false;
}
if (isArrayBuffer(a)) {
a = new Uint8Array(a);
b = new Uint8Array(b);
}
if (isView(a) && !isBuffer(a)) {
if (isBuffer(b))
return false;
const x = new Uint8Array(a.buffer);
const y = new Uint8Array(b.buffer);
if (x.length !== y.length)
return false;
for (let i = 0; i < x.length; i++) {
if (x[i] !== y[i])
return false;
}
return true;
}
if (isSet(a)) {
if (a.size !== b.size)
return false;
const keys = new Set([...a, ...b]);
return keys.size === a.size;
}
// Recursive.
if (!cache) {
cache = {
a: new Map(),
b: new Map(),
p: 0
};
} else {
const aa = cache.a.get(a);
if (aa != null) {
const bb = cache.b.get(b);
if (bb != null)
return aa === bb;
}
cache.p += 1;
}
cache.a.set(a, cache.p);
cache.b.set(b, cache.p);
const ret = recurse(a, b, cache);
cache.a.delete(a);
cache.b.delete(b);
return ret;
}
function recurse(a, b, cache) {
if (isMap(a)) {
if (a.size !== b.size)
return false;
const keys = new Set([...a.keys(), ...b.keys()]);
if (keys.size !== a.size)
return false;
for (const key of keys) {
if (!compare(a.get(key), b.get(key), cache))
return false;
}
return true;
}
if (isArray(a)) {
if (a.length !== b.length)
return false;
for (let i = 0; i < a.length; i++) {
if (!compare(a[i], b[i], cache))
return false;
}
return true;
}
const ak = ownKeys(a);
const bk = ownKeys(b);
if (ak.length !== bk.length)
return false;
const keys = new Set([...ak, ...bk]);
if (keys.size !== ak.length)
return false;
for (const key of keys) {
if (!compare(a[key], b[key], cache))
return false;
}
return true;
}
function ownKeys(obj) {
const keys = Object.keys(obj);
if (!Object.getOwnPropertySymbols)
return keys;
if (!Object.getOwnPropertyDescriptor)
return keys;
const symbols = Object.getOwnPropertySymbols(obj);
for (const symbol of symbols) {
const desc = Object.getOwnPropertyDescriptor(obj, symbol);
if (desc && desc.enumerable)
keys.push(symbol);
}
return keys;
}
/*
* Helpers
*/
function objectString(obj) {
if (obj === undefined)
return '[object Undefined]';
if (obj === null)
return '[object Null]';
try {
return Object.prototype.toString.call(obj);
} catch (e) {
return '[object Object]';
}
}
function objectType(obj) {
return objectString(obj).slice(8, -1);
}
function objectName(obj) {
const type = objectType(obj);
if (obj == null)
return type;
if (type !== 'Object' && type !== 'Error')
return type;
let ctor, name;
try {
ctor = obj.constructor;
} catch (e) {
;
}
if (ctor == null)
return type;
try {
name = ctor.name;
} catch (e) {
return type;
}
if (typeof name !== 'string' || name.length === 0)
return type;
return name;
}
function funcName(func) {
let name;
try {
name = func.name;
} catch (e) {
;
}
if (typeof name !== 'string' || name.length === 0)
return 'Function';
return `Function: ${name}`;
}
function isArray(obj) {
return Array.isArray(obj);
}
function isArrayBuffer(obj) {
return obj instanceof ArrayBuffer;
}
function isBuffer(obj) {
return isObject(obj)
&& typeof obj.writeUInt32LE === 'function'
&& typeof obj.equals === 'function';
}
function isDate(obj) {
return obj instanceof Date;
}
function isError(obj) {
return obj instanceof Error;
}
function isMap(obj) {
return obj instanceof Map;
}
function isObject(obj) {
return obj && typeof obj === 'object';
}
function isPromise(obj) {
return obj instanceof Promise;
}
function isRegExp(obj) {
return obj instanceof RegExp;
}
function isSet(obj) {
return obj instanceof Set;
}
function isView(obj) {
return ArrayBuffer.isView(obj);
}
function isEncoding(enc) {
if (typeof enc !== 'string')
return false;
switch (enc) {
case 'ascii':
case 'binary':
case 'base64':
case 'hex':
case 'latin1':
case 'ucs2':
case 'utf8':
case 'utf16le':
return true;
}
return false;
}
function bufferize(actual, expected, enc) {
if (typeof expected === 'string') {
if (!isBuffer(actual))
return null;
const {constructor} = actual;
if (!constructor || typeof constructor.from !== 'function')
return null;
if (!isEncoding(enc))
return null;
if (enc === 'hex' && (expected.length & 1))
return null;
const raw = constructor.from(expected, enc);
if (enc === 'hex' && raw.length !== (expected.length >>> 1))
return null;
return raw;
}
return expected;
}
/*
* API
*/
assert.AssertionError = AssertionError;
assert.assert = assert;
assert.strict = assert;
assert.ok = assert;
assert.equal = equal;
assert.notEqual = notEqual;
assert.strictEqual = equal;
assert.notStrictEqual = notEqual;
assert.fail = fail;
assert.throws = throws;
assert.doesNotThrow = doesNotThrow;
assert.rejects = rejects;
assert.doesNotReject = doesNotReject;
assert.ifError = ifError;
assert.deepEqual = deepEqual;
assert.notDeepEqual = notDeepEqual;
assert.deepStrictEqual = deepEqual;
assert.notDeepStrictEqual = notDeepEqual;
assert.bufferEqual = bufferEqual;
assert.notBufferEqual = notBufferEqual;
assert.enforce = enforce;
assert.range = range;
/*
* Expose
*/
module.exports = assert;
}],
[/* 3 */ 'bufio', '/lib/bufio.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* bufio.js - buffer utilities for javascript
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const custom = __node_require__(4 /* './custom' */);
const encoding = __node_require__(5 /* './encoding' */);
const enforce = __node_require__(6 /* './enforce' */);
const EncodingError = __node_require__(7 /* './error' */);
const BufferReader = __node_require__(8 /* './reader' */);
const BufferWriter = __node_require__(9 /* './writer' */);
const StaticWriter = __node_require__(10 /* './staticwriter' */);
const Struct = __node_require__(11 /* './struct' */);
exports.custom = custom;
exports.encoding = encoding;
exports.EncodingError = EncodingError;
exports.BufferReader = BufferReader;
exports.BufferWriter = BufferWriter;
exports.StaticWriter = StaticWriter;
exports.Struct = Struct;
exports.read = function read(data, zeroCopy) {
return new BufferReader(data, zeroCopy);
};
exports.write = function write(size) {
return size != null
? new StaticWriter(size)
: new BufferWriter();
};
exports.pool = function pool(size) {
return StaticWriter.pool(size);
};
function _read(func, size) {
return function(data, off) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
if (off + size > data.length)
throw new EncodingError(off, 'Out of bounds read');
return func(data, off);
};
}
function _readn(func) {
return function(data, off, len) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
enforce((len >>> 0) === len, 'len', 'integer');
if (off + len > data.length)
throw new EncodingError(off, 'Out of bounds read');
return func(data, off, len);
};
}
function _readvar(func) {
return function(data, off) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
return func(data, off);
};
}
function _write(func, size) {
return function(data, num, off) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
if (off + size > data.length)
throw new EncodingError(off, 'Out of bounds write');
return func(data, num, off);
};
}
function _writen(func) {
return function(data, num, off, len) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
enforce((len >>> 0) === len, 'len', 'integer');
if (off + len > data.length)
throw new EncodingError(off, 'Out of bounds write');
return func(data, num, off, len);
};
}
function _writecb(func, size) {
return function(data, num, off) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
if (off + size(num) > data.length)
throw new EncodingError(off, 'Out of bounds write');
return func(data, num, off);
};
}
exports.readU = _readn(encoding.readU);
exports.readU64 = _read(encoding.readU64, 8);
exports.readU56 = _read(encoding.readU56, 7);
exports.readU48 = _read(encoding.readU48, 6);
exports.readU40 = _read(encoding.readU40, 5);
exports.readU32 = _read(encoding.readU32, 4);
exports.readU24 = _read(encoding.readU24, 3);
exports.readU16 = _read(encoding.readU16, 2);
exports.readU8 = _read(encoding.readU8, 1);
exports.readUBE = _readn(encoding.readUBE);
exports.readU64BE = _read(encoding.readU64BE, 8);
exports.readU56BE = _read(encoding.readU56BE, 7);
exports.readU48BE = _read(encoding.readU48BE, 6);
exports.readU40BE = _read(encoding.readU40BE, 5);
exports.readU32BE = _read(encoding.readU32BE, 4);
exports.readU24BE = _read(encoding.readU24BE, 3);
exports.readU16BE = _read(encoding.readU16BE, 2);
exports.readI = _readn(encoding.readI);
exports.readI64 = _read(encoding.readI64, 8);
exports.readI56 = _read(encoding.readI56, 7);
exports.readI48 = _read(encoding.readI48, 6);
exports.readI40 = _read(encoding.readI40, 5);
exports.readI32 = _read(encoding.readI32, 4);
exports.readI24 = _read(encoding.readI24, 3);
exports.readI16 = _read(encoding.readI16, 2);
exports.readI8 = _read(encoding.readI8, 1);
exports.readIBE = _readn(encoding.readIBE);
exports.readI64BE = _read(encoding.readI64BE, 8);
exports.readI56BE = _read(encoding.readI56BE, 7);
exports.readI48BE = _read(encoding.readI48BE, 6);
exports.readI40BE = _read(encoding.readI40BE, 5);
exports.readI32BE = _read(encoding.readI32BE, 4);
exports.readI24BE = _read(encoding.readI24BE, 3);
exports.readI16BE = _read(encoding.readI16BE, 2);
exports.readFloat = _read(encoding.readFloat, 4);
exports.readFloatBE = _read(encoding.readFloatBE, 4);
exports.readDouble = _read(encoding.readDouble, 8);
exports.readDoubleBE = _read(encoding.readDoubleBE, 8);
exports.writeU = _writen(encoding.writeU);
exports.writeU64 = _write(encoding.writeU64, 8);
exports.writeU56 = _write(encoding.writeU56, 7);
exports.writeU48 = _write(encoding.writeU48, 6);
exports.writeU40 = _write(encoding.writeU40, 5);
exports.writeU32 = _write(encoding.writeU32, 4);
exports.writeU24 = _write(encoding.writeU24, 3);
exports.writeU16 = _write(encoding.writeU16, 2);
exports.writeU8 = _write(encoding.writeU8, 1);
exports.writeUBE = _writen(encoding.writeUBE);
exports.writeU64BE = _write(encoding.writeU64BE, 8);
exports.writeU56BE = _write(encoding.writeU56BE, 7);
exports.writeU48BE = _write(encoding.writeU48BE, 6);
exports.writeU40BE = _write(encoding.writeU40BE, 5);
exports.writeU32BE = _write(encoding.writeU32BE, 4);
exports.writeU24BE = _write(encoding.writeU24BE, 3);
exports.writeU16BE = _write(encoding.writeU16BE, 2);
exports.writeI = _writen(encoding.writeI);
exports.writeI64 = _write(encoding.writeI64, 8);
exports.writeI56 = _write(encoding.writeI56, 7);
exports.writeI48 = _write(encoding.writeI48, 6);
exports.writeI40 = _write(encoding.writeI40, 5);
exports.writeI32 = _write(encoding.writeI32, 4);
exports.writeI24 = _write(encoding.writeI24, 3);
exports.writeI16 = _write(encoding.writeI16, 2);
exports.writeI8 = _write(encoding.writeI8, 1);
exports.writeIBE = _writen(encoding.writeIBE);
exports.writeI64BE = _write(encoding.writeI64BE, 8);
exports.writeI56BE = _write(encoding.writeI56BE, 7);
exports.writeI48BE = _write(encoding.writeI48BE, 6);
exports.writeI40BE = _write(encoding.writeI40BE, 5);
exports.writeI32BE = _write(encoding.writeI32BE, 4);
exports.writeI24BE = _write(encoding.writeI24BE, 3);
exports.writeI16BE = _write(encoding.writeI16BE, 2);
exports.writeFloat = _write(encoding.writeFloat, 4);
exports.writeFloatBE = _write(encoding.writeFloatBE, 4);
exports.writeDouble = _write(encoding.writeDouble, 8);
exports.writeDoubleBE = _write(encoding.writeDoubleBE, 8);
exports.readVarint = _readvar(encoding.readVarint);
exports.writeVarint = _writecb(encoding.writeVarint, encoding.sizeVarint);
exports.sizeVarint = encoding.sizeVarint;
exports.readVarint2 = _readvar(encoding.readVarint2);
exports.writeVarint2 = _writecb(encoding.writeVarint2, encoding.sizeVarint2);
exports.sizeVarint2 = encoding.sizeVarint2;
exports.sliceBytes = encoding.sliceBytes;
exports.readBytes = encoding.readBytes;
exports.writeBytes = encoding.writeBytes;
exports.readString = encoding.readString;
exports.writeString = encoding.writeString;
exports.realloc = encoding.realloc;
exports.copy = encoding.copy;
exports.concat = encoding.concat;
exports.sizeVarBytes = encoding.sizeVarBytes;
exports.sizeVarlen = encoding.sizeVarlen;
exports.sizeVarString = encoding.sizeVarString;
}],
[/* 4 */ 'bufio', '/lib/custom-browser.js', function(exports, module, __filename, __dirname, __meta) {
'use strict';
exports.custom = 'inspect';
}],
[/* 5 */ 'bufio', '/lib/encoding.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* encoding.js - encoding utils for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
/* eslint no-implicit-coercion: "off" */
'use strict';
const enforce = __node_require__(6 /* './enforce' */);
const EncodingError = __node_require__(7 /* './error' */);
/*
* Constants
*/
const HI = 1 / 0x100000000;
const {MAX_SAFE_INTEGER} = Number;
const F32_ARRAY = new Float32Array(1);
const F328_ARRAY = new Uint8Array(F32_ARRAY.buffer);
const F64_ARRAY = new Float64Array(1);
const F648_ARRAY = new Uint8Array(F64_ARRAY.buffer);
F32_ARRAY[0] = -1;
const BIG_ENDIAN = F328_ARRAY[3] === 0;
/*
* Read Unsigned LE
*/
function readU(data, off, len) {
switch (len) {
case 8:
return readU64(data, off);
case 7:
return readU56(data, off);
case 6:
return readU48(data, off);
case 5:
return readU40(data, off);
case 4:
return readU32(data, off);
case 3:
return readU24(data, off);
case 2:
return readU16(data, off);
case 1:
return readU8(data, off);
default:
throw new EncodingError(off, 'Invalid read length');
}
}
function readU64(data, off) {
const hi = readU32(data, off + 4);
const lo = readU32(data, off);
check((hi & 0xffe00000) === 0, off, 'Number exceeds 2^53-1');
return hi * 0x100000000 + lo;
}
function readU56(data, off) {
const hi = readU24(data, off + 4);
const lo = readU32(data, off);
check((hi & 0xffe00000) === 0, off, 'Number exceeds 2^53-1');
return hi * 0x100000000 + lo;
}
function readU48(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off++] * 0x1000000
+ data[off++] * 0x100000000
+ data[off] * 0x10000000000);
}
function readU40(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off++] * 0x1000000
+ data[off] * 0x100000000);
}
function readU32(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off] * 0x1000000);
}
function readU24(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off] * 0x10000);
}
function readU16(data, off) {
return data[off++] + data[off] * 0x100;
}
function readU8(data, off) {
return data[off];
}
/*
* Read Unsigned BE
*/
function readUBE(data, off, len) {
switch (len) {
case 8:
return readU64BE(data, off);
case 7:
return readU56BE(data, off);
case 6:
return readU48BE(data, off);
case 5:
return readU40BE(data, off);
case 4:
return readU32BE(data, off);
case 3:
return readU24BE(data, off);
case 2:
return readU16BE(data, off);
case 1:
return readU8(data, off);
default:
throw new EncodingError(off, 'Invalid read length');
}
}
function readU64BE(data, off) {
const hi = readU32BE(data, off);
const lo = readU32BE(data, off + 4);
check((hi & 0xffe00000) === 0, off, 'Number exceeds 2^53-1');
return hi * 0x100000000 + lo;
}
function readU56BE(data, off) {
const hi = readU24BE(data, off);
const lo = readU32BE(data, off + 3);
check((hi & 0xffe00000) === 0, off, 'Number exceeds 2^53-1');
return hi * 0x100000000 + lo;
}
function readU48BE(data, off) {
return (data[off++] * 0x10000000000
+ data[off++] * 0x100000000
+ data[off++] * 0x1000000
+ data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function readU40BE(data, off) {
return (data[off++] * 0x100000000
+ data[off++] * 0x1000000
+ data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function readU32BE(data, off) {
return (data[off++] * 0x1000000
+ data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function readU24BE(data, off) {
return (data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function readU16BE(data, off) {
return data[off++] * 0x100 + data[off];
}
/*
* Read Signed LE
*/
function readI(data, off, len) {
switch (len) {
case 8:
return readI64(data, off);
case 7:
return readI56(data, off);
case 6:
return readI48(data, off);
case 5:
return readI40(data, off);
case 4:
return readI32(data, off);
case 3:
return readI24(data, off);
case 2:
return readI16(data, off);
case 1:
return readI8(data, off);
default:
throw new EncodingError(off, 'Invalid read length');
}
}
function readI64(data, off) {
const hi = readI32(data, off + 4);
const lo = readU32(data, off);
check(isSafe(hi, lo), 'Number exceeds 2^53-1');
return hi * 0x100000000 + lo;
}
function readI56(data, off) {
const hi = readI24(data, off + 4);
const lo = readU32(data, off);
check(isSafe(hi, lo), 'Number exceeds 2^53-1');
return hi * 0x100000000 + lo;
}
function readI48(data, off) {
const val = data[off + 4] + data[off + 5] * 0x100;
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off] * 0x1000000
+ (val | (val & 0x8000) * 0x1fffe) * 0x100000000);
}
function readI40(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off++] * 0x1000000
+ (data[off] | (data[off] & 0x80) * 0x1fffffe) * 0x100000000);
}
function readI32(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ (data[off] << 24));
}
function readI24(data, off) {
const val = (data[off++]
+ data[off++] * 0x100
+ data[off] * 0x10000);
return val | (val & 0x800000) * 0x1fe;
}
function readI16(data, off) {
const val = data[off++] + data[off] * 0x100;
return val | (val & 0x8000) * 0x1fffe;
}
function readI8(data, off) {
const val = data[off];
return val | (val & 0x80) * 0x1fffffe;
}
/*
* Read Signed BE
*/
function readIBE(data, off, len) {
switch (len) {
case 8:
return readI64BE(data, off);
case 7:
return readI56BE(data, off);
case 6:
return readI48BE(data, off);
case 5:
return readI40BE(data, off);
case 4:
return readI32BE(data, off);
case 3:
return readI24BE(data, off);
case 2:
return readI16BE(data, off);
case 1:
return readI8(data, off);
default:
throw new EncodingError(off, 'Invalid read length');
}
}
function readI64BE(data, off) {
const hi = readI32BE(data, off);
const lo = readU32BE(data, off + 4);
check(isSafe(hi, lo), 'Number exceeds 2^53-1');
return hi * 0x100000000 + lo;
}
function readI56BE(data, off) {
const hi = readI24BE(data, off);
const lo = readU32BE(data, off + 3);
check(isSafe(hi, lo), 'Number exceeds 2^53-1');
return hi * 0x100000000 + lo;
}
function readI48BE(data, off) {
const val = data[off++] * 0x100 + data[off++];
return ((val | (val & 0x8000) * 0x1fffe) * 0x100000000
+ data[off++] * 0x1000000
+ data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function readI40BE(data, off) {
const val = data[off++];
return ((val | (val & 0x80) * 0x1fffffe) * 0x100000000
+ data[off++] * 0x1000000
+ data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function readI32BE(data, off) {
return ((data[off++] << 24)
+ data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function readI24BE(data, off) {
const val = (data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
return val | (val & 0x800000) * 0x1fe;
}
function readI16BE(data, off) {
const val = data[off++] * 0x100 + data[off];
return val | (val & 0x8000) * 0x1fffe;
}
/*
* Read Float
*/
function _readFloatBackwards(data, off) {
F328_ARRAY[3] = data[off++];
F328_ARRAY[2] = data[off++];
F328_ARRAY[1] = data[off++];
F328_ARRAY[0] = data[off];
return F32_ARRAY[0];
}
function _readFloatForwards(data, off) {
F328_ARRAY[0] = data[off++];
F328_ARRAY[1] = data[off++];
F328_ARRAY[2] = data[off++];
F328_ARRAY[3] = data[off];
return F32_ARRAY[0];
}
function _readDoubleBackwards(data, off) {
F648_ARRAY[7] = data[off++];
F648_ARRAY[6] = data[off++];
F648_ARRAY[5] = data[off++];
F648_ARRAY[4] = data[off++];
F648_ARRAY[3] = data[off++];
F648_ARRAY[2] = data[off++];
F648_ARRAY[1] = data[off++];
F648_ARRAY[0] = data[off];
return F64_ARRAY[0];
}
function _readDoubleForwards(data, off) {
F648_ARRAY[0] = data[off++];
F648_ARRAY[1] = data[off++];
F648_ARRAY[2] = data[off++];
F648_ARRAY[3] = data[off++];
F648_ARRAY[4] = data[off++];
F648_ARRAY[5] = data[off++];
F648_ARRAY[6] = data[off++];
F648_ARRAY[7] = data[off];
return F64_ARRAY[0];
}
const readFloat = BIG_ENDIAN ? _readFloatBackwards : _readFloatForwards;
const readFloatBE = BIG_ENDIAN ? _readFloatForwards : _readFloatBackwards;
const readDouble = BIG_ENDIAN ? _readDoubleBackwards : _readDoubleForwards;
const readDoubleBE = BIG_ENDIAN ? _readDoubleForwards : _readDoubleBackwards;
/*
* Write Unsigned LE
*/
function writeU(dst, num, off, len) {
switch (len) {
case 8:
return writeU64(dst, num, off);
case 7:
return writeU56(dst, num, off);
case 6:
return writeU48(dst, num, off);
case 5:
return writeU40(dst, num, off);
case 4:
return writeU32(dst, num, off);
case 3:
return writeU24(dst, num, off);
case 2:
return writeU16(dst, num, off);
case 1:
return writeU8(dst, num, off);
default:
throw new EncodingError(off, 'Invalid write length');
}
}
function writeU64(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
return write64(dst, num, off, false);
}
function writeU56(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
return write56(dst, num, off, false);
}
function writeU48(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
const hi = (num * HI) | 0;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
dst[off++] = hi;
dst[off++] = hi >>> 8;
return off;
}
function writeU40(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
const hi = (num * HI) | 0;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
dst[off++] = hi;
return off;
}
function writeU32(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
return off;
}
function writeU24(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
return off;
}
function writeU16(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
dst[off++] = num;
dst[off++] = num >>> 8;
return off;
}
function writeU8(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
dst[off] = num;
return off + 1;
}
/*
* Write Unsigned BE
*/
function writeUBE(dst, num, off, len) {
switch (len) {
case 8:
return writeU64BE(dst, num, off);
case 7:
return writeU56BE(dst, num, off);
case 6:
return writeU48BE(dst, num, off);
case 5:
return writeU40BE(dst, num, off);
case 4:
return writeU32BE(dst, num, off);
case 3:
return writeU24BE(dst, num, off);
case 2:
return writeU16BE(dst, num, off);
case 1:
return writeU8(dst, num, off);
default:
throw new EncodingError(off, 'Invalid write length');
}
}
function writeU64BE(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
return write64(dst, num, off, true);
}
function writeU56BE(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
return write56(dst, num, off, true);
}
function writeU48BE(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
const hi = (num * HI) | 0;
dst[off++] = hi >>> 8;
dst[off++] = hi;
dst[off + 3] = num;
num >>>= 8;
dst[off + 2] = num;
num >>>= 8;
dst[off + 1] = num;
num >>>= 8;
dst[off] = num;
return off + 4;
}
function writeU40BE(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
const hi = (num * HI) | 0;
dst[off++] = hi;
dst[off + 3] = num;
num >>>= 8;
dst[off + 2] = num;
num >>>= 8;
dst[off + 1] = num;
num >>>= 8;
dst[off] = num;
return off + 4;
}
function writeU32BE(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
dst[off + 3] = num;
num >>>= 8;
dst[off + 2] = num;
num >>>= 8;
dst[off + 1] = num;
num >>>= 8;
dst[off] = num;
return off + 4;
}
function writeU24BE(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
dst[off + 2] = num;
num >>>= 8;
dst[off + 1] = num;
num >>>= 8;
dst[off] = num;
return off + 3;
}
function writeU16BE(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
dst[off++] = num >>> 8;
dst[off++] = num;
return off;
}
/*
* Write Signed LE
*/
function writeI(dst, num, off, len) {
switch (len) {
case 8:
return writeU64(dst, num, off);
case 7:
return writeU56(dst, num, off);
case 6:
return writeU48(dst, num, off);
case 5:
return writeU40(dst, num, off);
case 4:
return writeU24(dst, num, off);
case 3:
return writeU32(dst, num, off);
case 2:
return writeU16(dst, num, off);
case 1:
return writeU8(dst, num, off);
default:
throw new EncodingError(off, 'Invalid write length');
}
}
function writeI64(dst, num, off) {
return writeU64(dst, num, off);
}
function writeI56(dst, num, off) {
return writeU56(dst, num, off);
}
function writeI48(dst, num, off) {
return writeU48(dst, num, off);
}
function writeI40(dst, num, off) {
return writeU40(dst, num, off);
}
function writeI32(dst, num, off) {
return writeU32(dst, num, off);
}
function writeI24(dst, num, off) {
return writeU24(dst, num, off);
}
function writeI16(dst, num, off) {
return writeU16(dst, num, off);
}
function writeI8(dst, num, off) {
return writeU8(dst, num, off);
}
/*
* Write Signed BE
*/
function writeIBE(dst, num, off, len) {
switch (len) {
case 8:
return writeU64BE(dst, num, off);
case 7:
return writeU56BE(dst, num, off);
case 6:
return writeU48BE(dst, num, off);
case 5:
return writeU40BE(dst, num, off);
case 4:
return writeU32BE(dst, num, off);
case 3:
return writeU24BE(dst, num, off);
case 2:
return writeU16BE(dst, num, off);
case 1:
return writeU8(dst, num, off);
default:
throw new EncodingError(off, 'Invalid write length');
}
}
function writeI64BE(dst, num, off) {
return writeU64BE(dst, num, off);
}
function writeI56BE(dst, num, off) {
return writeU56BE(dst, num, off);
}
function writeI48BE(dst, num, off) {
return writeU48BE(dst, num, off);
}
function writeI40BE(dst, num, off) {
return writeU40BE(dst, num, off);
}
function writeI32BE(dst, num, off) {
return writeU32BE(dst, num, off);
}
function writeI24BE(dst, num, off) {
return writeU24BE(dst, num, off);
}
function writeI16BE(dst, num, off) {
return writeU16BE(dst, num, off);
}
function _writeDoubleForwards(dst, num, off) {
enforce(isNumber(num), 'num', 'number');
F64_ARRAY[0] = num;
dst[off++] = F648_ARRAY[0];
dst[off++] = F648_ARRAY[1];
dst[off++] = F648_ARRAY[2];
dst[off++] = F648_ARRAY[3];
dst[off++] = F648_ARRAY[4];
dst[off++] = F648_ARRAY[5];
dst[off++] = F648_ARRAY[6];
dst[off++] = F648_ARRAY[7];
return off;
}
function _writeDoubleBackwards(dst, num, off) {
enforce(isNumber(num), 'num', 'number');
F64_ARRAY[0] = num;
dst[off++] = F648_ARRAY[7];
dst[off++] = F648_ARRAY[6];
dst[off++] = F648_ARRAY[5];
dst[off++] = F648_ARRAY[4];
dst[off++] = F648_ARRAY[3];
dst[off++] = F648_ARRAY[2];
dst[off++] = F648_ARRAY[1];
dst[off++] = F648_ARRAY[0];
return off;
}
function _writeFloatForwards(dst, num, off) {
enforce(isNumber(num), 'num', 'number');
F32_ARRAY[0] = num;
dst[off++] = F328_ARRAY[0];
dst[off++] = F328_ARRAY[1];
dst[off++] = F328_ARRAY[2];
dst[off++] = F328_ARRAY[3];
return off;
}
function _writeFloatBackwards(dst, num, off) {
enforce(isNumber(num), 'num', 'number');
F32_ARRAY[0] = num;
dst[off++] = F328_ARRAY[3];
dst[off++] = F328_ARRAY[2];
dst[off++] = F328_ARRAY[1];
dst[off++] = F328_ARRAY[0];
return off;
}
const writeFloat = BIG_ENDIAN ? _writeFloatBackwards : _writeFloatForwards;
const writeFloatBE = BIG_ENDIAN ? _writeFloatForwards : _writeFloatBackwards;
const writeDouble = BIG_ENDIAN ? _writeDoubleBackwards : _writeDoubleForwards;
const writeDoubleBE = BIG_ENDIAN ? _writeDoubleForwards : _writeDoubleBackwards;
/*
* Varints
*/
function readVarint(data, off) {
let value, size;
checkRead(off < data.length, off);
switch (data[off]) {
case 0xff:
size = 9;
checkRead(off + size <= data.length, off);
value = readU64(data, off + 1);
check(value > 0xffffffff, off, 'Non-canonical varint');
break;
case 0xfe:
size = 5;
checkRead(off + size <= data.length, off);
value = readU32(data, off + 1);
check(value > 0xffff, off, 'Non-canonical varint');
break;
case 0xfd:
size = 3;
checkRead(off + size <= data.length, off);
value = readU16(data, off + 1);
check(value >= 0xfd, off, 'Non-canonical varint');
break;
default:
size = 1;
value = data[off];
break;
}
return new Varint(size, value);
}
function writeVarint(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
if (num < 0xfd) {
dst[off++] = num;
return off;
}
if (num <= 0xffff) {
dst[off++] = 0xfd;
return writeU16(dst, num, off);
}
if (num <= 0xffffffff) {
dst[off++] = 0xfe;
return writeU32(dst, num, off);
}
dst[off++] = 0xff;
return writeU64(dst, num, off);
}
function sizeVarint(num) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
if (num < 0xfd)
return 1;
if (num <= 0xffff)
return 3;
if (num <= 0xffffffff)
return 5;
return 9;
}
function readVarint2(data, off) {
let num = 0;
let size = 0;
for (;;) {
checkRead(off < data.length, off);
const ch = data[off++];
size += 1;
// Number.MAX_SAFE_INTEGER >>> 7
check(num <= 0x3fffffffffff - (ch & 0x7f), off, 'Number exceeds 2^53-1');
// num = (num << 7) | (ch & 0x7f);
num = (num * 0x80) + (ch & 0x7f);
if ((ch & 0x80) === 0)
break;
check(num !== MAX_SAFE_INTEGER, off, 'Number exceeds 2^53-1');
num += 1;
}
return new Varint(size, num);
}
function writeVarint2(dst, num, off) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
const tmp = [];
let len = 0;
for (;;) {
tmp[len] = (num & 0x7f) | (len ? 0x80 : 0x00);
if (num <= 0x7f)
break;
// num = (num >>> 7) - 1;
num = ((num - (num % 0x80)) / 0x80) - 1;
len += 1;
}
checkRead(off + len + 1 <= dst.length, off);
do {
dst[off++] = tmp[len];
} while (len--);
return off;
}
function sizeVarint2(num) {
enforce(Number.isSafeInteger(num), 'num', 'integer');
let size = 0;
for (;;) {
size += 1;
if (num <= 0x7f)
break;
// num = (num >>> 7) - 1;
num = ((num - (num % 0x80)) / 0x80) - 1;
}
return size;
}
/*
* Bytes
*/
function sliceBytes(data, off, size) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
enforce((size >>> 0) === size, 'size', 'integer');
if (off + size > data.length)
throw new EncodingError(off, 'Out of bounds read');
return data.slice(off, off + size);
}
function readBytes(data, off, size) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
enforce((size >>> 0) === size, 'size', 'integer');
if (off + size > data.length)
throw new EncodingError(off, 'Out of bounds read');
const buf = Buffer.allocUnsafeSlow(size);
data.copy(buf, 0, off, off + size);
return buf;
}
function writeBytes(data, value, off) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce(Buffer.isBuffer(value), 'value', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
if (off + value.length > data.length)
throw new EncodingError(off, 'Out of bounds write');
return value.copy(data, off, 0, value.length);
}
function readString(data, off, size, enc) {
if (enc == null)
enc = 'binary';
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce((off >>> 0) === off, 'off', 'integer');
enforce((size >>> 0) === size, 'size', 'integer');
enforce(typeof enc === 'string', 'enc', 'string');
if (off + size > data.length)
throw new EncodingError(off, 'Out of bounds read');
return data.toString(enc, off, off + size);
}
function writeString(data, str, off, enc) {
if (enc == null)
enc = 'binary';
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce(typeof str === 'string', 'str', 'string');
enforce((off >>> 0) === off, 'off', 'integer');
enforce(typeof enc === 'string', 'enc', 'string');
if (str.length === 0)
return 0;
const size = Buffer.byteLength(str, enc);
if (off + size > data.length)
throw new EncodingError(off, 'Out of bounds write');
return data.write(str, off, enc);
}
function realloc(data, size) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
const buf = Buffer.allocUnsafeSlow(size);
data.copy(buf, 0);
return buf;
}
function copy(data) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
return realloc(data, data.length);
}
function concat(a, b) {
enforce(Buffer.isBuffer(a), 'a', 'buffer');
enforce(Buffer.isBuffer(b), 'b', 'buffer');
const size = a.length + b.length;
const buf = Buffer.allocUnsafeSlow(size);
a.copy(buf, 0);
b.copy(buf, a.length);
return buf;
}
/*
* Size Helpers
*/
function sizeVarBytes(data) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
return sizeVarint(data.length) + data.length;
}
function sizeVarlen(len) {
return sizeVarint(len) + len;
}
function sizeVarString(str, enc) {
if (enc == null)
enc = 'binary';
enforce(typeof str === 'string', 'str', 'string');
enforce(typeof enc === 'string', 'enc', 'string');
if (str.length === 0)
return 1;
const len = Buffer.byteLength(str, enc);
return sizeVarint(len) + len;
}
/*
* Helpers
*/
function isSafe(hi, lo) {
if (hi < 0) {
hi = ~hi;
if (lo === 0)
hi += 1;
}
return (hi & 0xffe00000) === 0;
}
function write64(dst, num, off, be) {
let neg = false;
if (num < 0) {
num = -num;
neg = true;
}
let hi = (num * HI) | 0;
let lo = num | 0;
if (neg) {
if (lo === 0) {
hi = (~hi + 1) | 0;
} else {
hi = ~hi;
lo = ~lo + 1;
}
}
if (be) {
off = writeI32BE(dst, hi, off);
off = writeI32BE(dst, lo, off);
} else {
off = writeI32(dst, lo, off);
off = writeI32(dst, hi, off);
}
return off;
}
function write56(dst, num, off, be) {
let neg = false;
if (num < 0) {
num = -num;
neg = true;
}
let hi = (num * HI) | 0;
let lo = num | 0;
if (neg) {
if (lo === 0) {
hi = (~hi + 1) | 0;
} else {
hi = ~hi;
lo = ~lo + 1;
}
}
if (be) {
off = writeI24BE(dst, hi, off);
off = writeI32BE(dst, lo, off);
} else {
off = writeI32(dst, lo, off);
off = writeI24(dst, hi, off);
}
return off;
}
class Varint {
constructor(size, value) {
this.size = size;
this.value = value;
}
}
function isNumber(num) {
return typeof num === 'number' && isFinite(num);
}
function checkRead(value, offset) {
if (!value)
throw new EncodingError(offset, 'Out of bounds read', checkRead);
}
function check(value, offset, reason) {
if (!value)
throw new EncodingError(offset, reason, check);
}
/*
* Expose
*/
exports.readU = readU;
exports.readU64 = readU64;
exports.readU56 = readU56;
exports.readU48 = readU48;
exports.readU40 = readU40;
exports.readU32 = readU32;
exports.readU24 = readU24;
exports.readU16 = readU16;
exports.readU8 = readU8;
exports.readUBE = readUBE;
exports.readU64BE = readU64BE;
exports.readU56BE = readU56BE;
exports.readU48BE = readU48BE;
exports.readU40BE = readU40BE;
exports.readU32BE = readU32BE;
exports.readU24BE = readU24BE;
exports.readU16BE = readU16BE;
exports.readI = readI;
exports.readI64 = readI64;
exports.readI56 = readI56;
exports.readI48 = readI48;
exports.readI40 = readI40;
exports.readI32 = readI32;
exports.readI24 = readI24;
exports.readI16 = readI16;
exports.readI8 = readI8;
exports.readIBE = readIBE;
exports.readI64BE = readI64BE;
exports.readI56BE = readI56BE;
exports.readI48BE = readI48BE;
exports.readI40BE = readI40BE;
exports.readI32BE = readI32BE;
exports.readI24BE = readI24BE;
exports.readI16BE = readI16BE;
exports.readFloat = readFloat;
exports.readFloatBE = readFloatBE;
exports.readDouble = readDouble;
exports.readDoubleBE = readDoubleBE;
exports.writeU = writeU;
exports.writeU64 = writeU64;
exports.writeU56 = writeU56;
exports.writeU48 = writeU48;
exports.writeU40 = writeU40;
exports.writeU32 = writeU32;
exports.writeU24 = writeU24;
exports.writeU16 = writeU16;
exports.writeU8 = writeU8;
exports.writeUBE = writeUBE;
exports.writeU64BE = writeU64BE;
exports.writeU56BE = writeU56BE;
exports.writeU48BE = writeU48BE;
exports.writeU40BE = writeU40BE;
exports.writeU32BE = writeU32BE;
exports.writeU24BE = writeU24BE;
exports.writeU16BE = writeU16BE;
exports.writeI = writeI;
exports.writeI64 = writeI64;
exports.writeI56 = writeI56;
exports.writeI48 = writeI48;
exports.writeI40 = writeI40;
exports.writeI32 = writeI32;
exports.writeI24 = writeI24;
exports.writeI16 = writeI16;
exports.writeI8 = writeI8;
exports.writeIBE = writeIBE;
exports.writeI64BE = writeI64BE;
exports.writeI56BE = writeI56BE;
exports.writeI48BE = writeI48BE;
exports.writeI40BE = writeI40BE;
exports.writeI32BE = writeI32BE;
exports.writeI24BE = writeI24BE;
exports.writeI16BE = writeI16BE;
exports.writeFloat = writeFloat;
exports.writeFloatBE = writeFloatBE;
exports.writeDouble = writeDouble;
exports.writeDoubleBE = writeDoubleBE;
exports.readVarint = readVarint;
exports.writeVarint = writeVarint;
exports.sizeVarint = sizeVarint;
exports.readVarint2 = readVarint2;
exports.writeVarint2 = writeVarint2;
exports.sizeVarint2 = sizeVarint2;
exports.sliceBytes = sliceBytes;
exports.readBytes = readBytes;
exports.writeBytes = writeBytes;
exports.readString = readString;
exports.writeString = writeString;
exports.realloc = realloc;
exports.copy = copy;
exports.concat = concat;
exports.sizeVarBytes = sizeVarBytes;
exports.sizeVarlen = sizeVarlen;
exports.sizeVarString = sizeVarString;
}],
[/* 6 */ 'bufio', '/lib/enforce.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* enforce.js - type enforcement for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/*
* Enforce
*/
function enforce(value, name, type) {
if (!value) {
const err = new TypeError(`'${name}' must be a(n) ${type}.`);
if (Error.captureStackTrace)
Error.captureStackTrace(err, enforce);
throw err;
}
}
/*
* Expose
*/
module.exports = enforce;
}],
[/* 7 */ 'bufio', '/lib/error.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* error.js - encoding error for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* Encoding Error
* @extends {Error}
*/
class EncodingError extends Error {
/**
* Create an encoding error.
* @constructor
* @param {Number} offset
* @param {String} reason
*/
constructor(offset, reason, start) {
super();
this.type = 'EncodingError';
this.name = 'EncodingError';
this.code = 'ERR_ENCODING';
this.message = `${reason} (offset=${offset}).`;
if (Error.captureStackTrace)
Error.captureStackTrace(this, start || EncodingError);
}
}
/*
* Expose
*/
module.exports = EncodingError;
}],
[/* 8 */ 'bufio', '/lib/reader.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* reader.js - buffer reader for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const enforce = __node_require__(6 /* './enforce' */);
const encoding = __node_require__(5 /* './encoding' */);
const EncodingError = __node_require__(7 /* './error' */);
/*
* Constants
*/
const EMPTY = Buffer.alloc(0);
/**
* Buffer Reader
*/
class BufferReader {
/**
* Create a buffer reader.
* @constructor
* @param {Buffer} data
* @param {Boolean?} zeroCopy - Do not reallocate buffers when
* slicing. Note that this can lead to memory leaks if not used
* carefully.
*/
constructor(data, zeroCopy = false) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
enforce(typeof zeroCopy === 'boolean', 'zeroCopy', 'boolean');
this.data = data;
this.offset = 0;
this.zeroCopy = zeroCopy;
this.stack = [];
}
/**
* Assertion.
* @param {Number} size
*/
check(size) {
if (this.offset + size > this.data.length)
throw new EncodingError(this.offset, 'Out of bounds read', this.check);
}
/**
* Get total size of passed-in Buffer.
* @returns {Buffer}
*/
getSize() {
return this.data.length;
}
/**
* Calculate number of bytes left to read.
* @returns {Number}
*/
left() {
this.check(0);
return this.data.length - this.offset;
}
/**
* Seek to a position to read from by offset.
* @param {Number} off - Offset (positive or negative).
*/
seek(off) {
enforce(Number.isSafeInteger(off), 'off', 'integer');
if (this.offset + off < 0)
throw new EncodingError(this.offset, 'Out of bounds read');
this.check(off);
this.offset += off;
return this;
}
/**
* Mark the current starting position.
*/
start() {
this.stack.push(this.offset);
return this.offset;
}
/**
* Stop reading. Pop the start position off the stack
* and calculate the size of the data read.
* @returns {Number} Size.
* @throws on empty stack.
*/
end() {
if (this.stack.length === 0)
throw new Error('Cannot end without a stack item.');
const start = this.stack.pop();
return this.offset - start;
}
/**
* Stop reading. Pop the start position off the stack
* and return the data read.
* @param {Bolean?} zeroCopy - Do a fast buffer
* slice instead of allocating a new buffer (warning:
* may cause memory leaks if not used with care).
* @returns {Buffer} Data read.
* @throws on empty stack.
*/
endData(zeroCopy = false) {
enforce(typeof zeroCopy === 'boolean', 'zeroCopy', 'boolean');
if (this.stack.length === 0)
throw new Error('Cannot end without a stack item.');
const start = this.stack.pop();
const end = this.offset;
const size = end - start;
const data = this.data;
if (size === data.length)
return data;
if (this.zeroCopy || zeroCopy)
return data.slice(start, end);
const ret = Buffer.allocUnsafeSlow(size);
data.copy(ret, 0, start, end);
return ret;
}
/**
* Destroy the reader. Remove references to the data.
*/
destroy() {
this.data = EMPTY;
this.offset = 0;
this.stack.length = 0;
return this;
}
/**
* Read uint8.
* @returns {Number}
*/
readU8() {
this.check(1);
const ret = this.data[this.offset];
this.offset += 1;
return ret;
}
/**
* Read uint16le.
* @returns {Number}
*/
readU16() {
this.check(2);
const ret = encoding.readU16(this.data, this.offset);
this.offset += 2;
return ret;
}
/**
* Read uint16be.
* @returns {Number}
*/
readU16BE() {
this.check(2);
const ret = encoding.readU16BE(this.data, this.offset);
this.offset += 2;
return ret;
}
/**
* Read uint24le.
* @returns {Number}
*/
readU24() {
this.check(3);
const ret = encoding.readU24(this.data, this.offset);
this.offset += 3;
return ret;
}
/**
* Read uint24be.
* @returns {Number}
*/
readU24BE() {
this.check(3);
const ret = encoding.readU24BE(this.data, this.offset);
this.offset += 3;
return ret;
}
/**
* Read uint32le.
* @returns {Number}
*/
readU32() {
this.check(4);
const ret = encoding.readU32(this.data, this.offset);
this.offset += 4;
return ret;
}
/**
* Read uint32be.
* @returns {Number}
*/
readU32BE() {
this.check(4);
const ret = encoding.readU32BE(this.data, this.offset);
this.offset += 4;
return ret;
}
/**
* Read uint40le.
* @returns {Number}
*/
readU40() {
this.check(5);
const ret = encoding.readU40(this.data, this.offset);
this.offset += 5;
return ret;
}
/**
* Read uint40be.
* @returns {Number}
*/
readU40BE() {
this.check(5);
const ret = encoding.readU40BE(this.data, this.offset);
this.offset += 5;
return ret;
}
/**
* Read uint48le.
* @returns {Number}
*/
readU48() {
this.check(6);
const ret = encoding.readU48(this.data, this.offset);
this.offset += 6;
return ret;
}
/**
* Read uint48be.
* @returns {Number}
*/
readU48BE() {
this.check(6);
const ret = encoding.readU48BE(this.data, this.offset);
this.offset += 6;
return ret;
}
/**
* Read uint56le.
* @returns {Number}
*/
readU56() {
this.check(7);
const ret = encoding.readU56(this.data, this.offset);
this.offset += 7;
return ret;
}
/**
* Read uint56be.
* @returns {Number}
*/
readU56BE() {
this.check(7);
const ret = encoding.readU56BE(this.data, this.offset);
this.offset += 7;
return ret;
}
/**
* Read uint64le as a js number.
* @returns {Number}
* @throws on num > MAX_SAFE_INTEGER
*/
readU64() {
this.check(8);
const ret = encoding.readU64(this.data, this.offset);
this.offset += 8;
return ret;
}
/**
* Read uint64be as a js number.
* @returns {Number}
* @throws on num > MAX_SAFE_INTEGER
*/
readU64BE() {
this.check(8);
const ret = encoding.readU64BE(this.data, this.offset);
this.offset += 8;
return ret;
}
/**
* Read int8.
* @returns {Number}
*/
readI8() {
this.check(1);
const ret = encoding.readI8(this.data, this.offset);
this.offset += 1;
return ret;
}
/**
* Read int16le.
* @returns {Number}
*/
readI16() {
this.check(2);
const ret = encoding.readI16(this.data, this.offset);
this.offset += 2;
return ret;
}
/**
* Read int16be.
* @returns {Number}
*/
readI16BE() {
this.check(2);
const ret = encoding.readI16BE(this.data, this.offset);
this.offset += 2;
return ret;
}
/**
* Read int24le.
* @returns {Number}
*/
readI24() {
this.check(3);
const ret = encoding.readI24(this.data, this.offset);
this.offset += 3;
return ret;
}
/**
* Read int24be.
* @returns {Number}
*/
readI24BE() {
this.check(3);
const ret = encoding.readI24BE(this.data, this.offset);
this.offset += 3;
return ret;
}
/**
* Read int32le.
* @returns {Number}
*/
readI32() {
this.check(4);
const ret = encoding.readI32(this.data, this.offset);
this.offset += 4;
return ret;
}
/**
* Read int32be.
* @returns {Number}
*/
readI32BE() {
this.check(4);
const ret = encoding.readI32BE(this.data, this.offset);
this.offset += 4;
return ret;
}
/**
* Read int40le.
* @returns {Number}
*/
readI40() {
this.check(5);
const ret = encoding.readI40(this.data, this.offset);
this.offset += 5;
return ret;
}
/**
* Read int40be.
* @returns {Number}
*/
readI40BE() {
this.check(5);
const ret = encoding.readI40BE(this.data, this.offset);
this.offset += 5;
return ret;
}
/**
* Read int48le.
* @returns {Number}
*/
readI48() {
this.check(6);
const ret = encoding.readI48(this.data, this.offset);
this.offset += 6;
return ret;
}
/**
* Read int48be.
* @returns {Number}
*/
readI48BE() {
this.check(6);
const ret = encoding.readI48BE(this.data, this.offset);
this.offset += 6;
return ret;
}
/**
* Read int56le.
* @returns {Number}
*/
readI56() {
this.check(7);
const ret = encoding.readI56(this.data, this.offset);
this.offset += 7;
return ret;
}
/**
* Read int56be.
* @returns {Number}
*/
readI56BE() {
this.check(7);
const ret = encoding.readI56BE(this.data, this.offset);
this.offset += 7;
return ret;
}
/**
* Read int64le as a js number.
* @returns {Number}
* @throws on num > MAX_SAFE_INTEGER
*/
readI64() {
this.check(8);
const ret = encoding.readI64(this.data, this.offset);
this.offset += 8;
return ret;
}
/**
* Read int64be as a js number.
* @returns {Number}
* @throws on num > MAX_SAFE_INTEGER
*/
readI64BE() {
this.check(8);
const ret = encoding.readI64BE(this.data, this.offset);
this.offset += 8;
return ret;
}
/**
* Read float le.
* @returns {Number}
*/
readFloat() {
this.check(4);
const ret = encoding.readFloat(this.data, this.offset);
this.offset += 4;
return ret;
}
/**
* Read float be.
* @returns {Number}
*/
readFloatBE() {
this.check(4);
const ret = encoding.readFloatBE(this.data, this.offset);
this.offset += 4;
return ret;
}
/**
* Read double float le.
* @returns {Number}
*/
readDouble() {
this.check(8);
const ret = encoding.readDouble(this.data, this.offset);
this.offset += 8;
return ret;
}
/**
* Read double float be.
* @returns {Number}
*/
readDoubleBE() {
this.check(8);
const ret = encoding.readDoubleBE(this.data, this.offset);
this.offset += 8;
return ret;
}
/**
* Read a varint.
* @returns {Number}
*/
readVarint() {
const {size, value} = encoding.readVarint(this.data, this.offset);
this.offset += size;
return value;
}
/**
* Read a varint (type 2).
* @returns {Number}
*/
readVarint2() {
const {size, value} = encoding.readVarint2(this.data, this.offset);
this.offset += size;
return value;
}
/**
* Read N bytes (will do a fast slice if zero copy).
* @param {Number} size
* @param {Bolean?} zeroCopy - Do a fast buffer
* slice instead of allocating a new buffer (warning:
* may cause memory leaks if not used with care).
* @returns {Buffer}
*/
readBytes(size, zeroCopy = false) {
enforce((size >>> 0) === size, 'size', 'integer');
enforce(typeof zeroCopy === 'boolean', 'zeroCopy', 'boolean');
this.check(size);
let ret;
if (this.zeroCopy || zeroCopy) {
ret = this.data.slice(this.offset, this.offset + size);
} else {
ret = Buffer.allocUnsafeSlow(size);
this.data.copy(ret, 0, this.offset, this.offset + size);
}
this.offset += size;
return ret;
}
/**
* Read a varint number of bytes (will do a fast slice if zero copy).
* @param {Bolean?} zeroCopy - Do a fast buffer
* slice instead of allocating a new buffer (warning:
* may cause memory leaks if not used with care).
* @returns {Buffer}
*/
readVarBytes(zeroCopy = false) {
return this.readBytes(this.readVarint(), zeroCopy);
}
/**
* Slice N bytes and create a child reader.
* @param {Number} size
* @returns {BufferReader}
*/
readChild(size) {
enforce((size >>> 0) === size, 'size', 'integer');
this.check(size);
const data = this.data.slice(0, this.offset + size);
const br = new this.constructor(data);
br.offset = this.offset;
this.offset += size;
return br;
}
/**
* Read a string.
* @param {Number} size
* @param {String} enc - Any buffer-supported encoding.
* @returns {String}
*/
readString(size, enc) {
if (enc == null)
enc = 'binary';
enforce((size >>> 0) === size, 'size', 'integer');
enforce(typeof enc === 'string', 'enc', 'string');
this.check(size);
const ret = this.data.toString(enc, this.offset, this.offset + size);
this.offset += size;
return ret;
}
/**
* Read a 32-byte hash.
* @param {String} enc - `"hex"` or `null`.
* @returns {Hash|Buffer}
*/
readHash(enc) {
if (enc)
return this.readString(32, enc);
return this.readBytes(32);
}
/**
* Read string of a varint length.
* @param {String} enc - Any buffer-supported encoding.
* @param {Number?} limit - Size limit.
* @returns {String}
*/
readVarString(enc, limit = 0) {
if (enc == null)
enc = 'binary';
enforce(typeof enc === 'string', 'enc', 'string');
enforce((limit >>> 0) === limit, 'limit', 'integer');
const size = this.readVarint();
if (limit !== 0 && size > limit)
throw new EncodingError(this.offset, 'String exceeds limit');
return this.readString(size, enc);
}
/**
* Read a null-terminated string.
* @param {String} enc - Any buffer-supported encoding.
* @returns {String}
*/
readNullString(enc) {
if (enc == null)
enc = 'binary';
enforce(typeof enc === 'string', 'enc', 'string');
let i = this.offset;
for (; i < this.data.length; i++) {
if (this.data[i] === 0)
break;
}
if (i === this.data.length)
throw new EncodingError(this.offset, 'No NUL terminator');
const ret = this.readString(i - this.offset, enc);
this.offset = i + 1;
return ret;
}
/**
* Create a checksum from the last start position.
* @param {Function} hash
* @returns {Number} Checksum.
*/
createChecksum(hash) {
if (!hash || typeof hash.digest !== 'function')
enforce(typeof hash === 'function', 'hash', 'function');
let start = 0;
if (this.stack.length > 0)
start = this.stack[this.stack.length - 1];
const data = this.data.slice(start, this.offset);
const raw = hash.digest ? hash.digest(data) : hash(data);
return encoding.readU32(raw, 0);
}
/**
* Verify a 4-byte checksum against a calculated checksum.
* @param {Function} hash
* @returns {Number} checksum
* @throws on bad checksum
*/
verifyChecksum(hash) {
const checksum = this.createChecksum(hash);
const expect = this.readU32();
if (checksum !== expect)
throw new EncodingError(this.offset, 'Checksum mismatch');
return checksum;
}
}
/*
* Expose
*/
module.exports = BufferReader;
}],
[/* 9 */ 'bufio', '/lib/writer.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* writer.js - buffer writer for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const enforce = __node_require__(6 /* './enforce' */);
const encoding = __node_require__(5 /* './encoding' */);
const EncodingError = __node_require__(7 /* './error' */);
/*
* Constants
*/
const SEEK = 0;
const U8 = 1;
const U16 = 2;
const U16BE = 3;
const U24 = 4;
const U24BE = 5;
const U32 = 6;
const U32BE = 7;
const U40 = 8;
const U40BE = 9;
const U48 = 10;
const U48BE = 11;
const U56 = 12;
const U56BE = 13;
const U64 = 14;
const U64BE = 15;
const I8 = 16;
const I16 = 17;
const I16BE = 18;
const I24 = 19;
const I24BE = 20;
const I32 = 21;
const I32BE = 22;
const I40 = 23;
const I40BE = 24;
const I48 = 25;
const I48BE = 26;
const I56 = 27;
const I56BE = 28;
const I64 = 29;
const I64BE = 30;
const FL = 31;
const FLBE = 32;
const DBL = 33;
const DBLBE = 34;
const VARINT = 35;
const VARINT2 = 36;
const BYTES = 37;
const STR = 38;
const CHECKSUM = 39;
const FILL = 40;
/**
* Buffer Writer
*/
class BufferWriter {
/**
* Create a buffer writer.
* @constructor
*/
constructor() {
this.ops = [];
this.offset = 0;
}
/**
* Allocate and render the final buffer.
* @returns {Buffer} Rendered buffer.
*/
render() {
const data = Buffer.allocUnsafeSlow(this.offset);
let off = 0;
for (const op of this.ops) {
switch (op.type) {
case SEEK:
off += op.value;
break;
case U8:
off = encoding.writeU8(data, op.value, off);
break;
case U16:
off = encoding.writeU16(data, op.value, off);
break;
case U16BE:
off = encoding.writeU16BE(data, op.value, off);
break;
case U24:
off = encoding.writeU24(data, op.value, off);
break;
case U24BE:
off = encoding.writeU24BE(data, op.value, off);
break;
case U32:
off = encoding.writeU32(data, op.value, off);
break;
case U32BE:
off = encoding.writeU32BE(data, op.value, off);
break;
case U40:
off = encoding.writeU40(data, op.value, off);
break;
case U40BE:
off = encoding.writeU40BE(data, op.value, off);
break;
case U48:
off = encoding.writeU48(data, op.value, off);
break;
case U48BE:
off = encoding.writeU48BE(data, op.value, off);
break;
case U56:
off = encoding.writeU56(data, op.value, off);
break;
case U56BE:
off = encoding.writeU56BE(data, op.value, off);
break;
case U64:
off = encoding.writeU64(data, op.value, off);
break;
case U64BE:
off = encoding.writeU64BE(data, op.value, off);
break;
case I8:
off = encoding.writeI8(data, op.value, off);
break;
case I16:
off = encoding.writeI16(data, op.value, off);
break;
case I16BE:
off = encoding.writeI16BE(data, op.value, off);
break;
case I24:
off = encoding.writeI24(data, op.value, off);
break;
case I24BE:
off = encoding.writeI24BE(data, op.value, off);
break;
case I32:
off = encoding.writeI32(data, op.value, off);
break;
case I32BE:
off = encoding.writeI32BE(data, op.value, off);
break;
case I40:
off = encoding.writeI40(data, op.value, off);
break;
case I40BE:
off = encoding.writeI40BE(data, op.value, off);
break;
case I48:
off = encoding.writeI48(data, op.value, off);
break;
case I48BE:
off = encoding.writeI48BE(data, op.value, off);
break;
case I56:
off = encoding.writeI56(data, op.value, off);
break;
case I56BE:
off = encoding.writeI56BE(data, op.value, off);
break;
case I64:
off = encoding.writeI64(data, op.value, off);
break;
case I64BE:
off = encoding.writeI64BE(data, op.value, off);
break;
case FL:
off = encoding.writeFloat(data, op.value, off);
break;
case FLBE:
off = encoding.writeFloatBE(data, op.value, off);
break;
case DBL:
off = encoding.writeDouble(data, op.value, off);
break;
case DBLBE:
off = encoding.writeDoubleBE(data, op.value, off);
break;
case VARINT:
off = encoding.writeVarint(data, op.value, off);
break;
case VARINT2:
off = encoding.writeVarint2(data, op.value, off);
break;
case BYTES:
off += op.data.copy(data, off);
break;
case STR:
off += data.write(op.value, off, op.enc);
break;
case CHECKSUM:
off += op.func(data.slice(0, off)).copy(data, off, 0, 4);
break;
case FILL:
data.fill(op.value, off, off + op.size);
off += op.size;
break;
default:
throw new Error('Invalid type.');
}
}
if (off !== data.length)
throw new EncodingError(off, 'Out of bounds write');
this.destroy();
return data;
}
/**
* Get size of data written so far.
* @returns {Number}
*/
getSize() {
return this.offset;
}
/**
* Seek to relative offset.
* @param {Number} offset
*/
seek(off) {
enforce(Number.isSafeInteger(off), 'off', 'integer');
if (this.offset + off < 0)
throw new EncodingError(this.offset, 'Out of bounds write');
this.offset += off;
this.ops.push(new NumberOp(SEEK, off));
return this;
}
/**
* Destroy the buffer writer. Remove references to `ops`.
*/
destroy() {
this.ops.length = 0;
this.offset = 0;
return this;
}
/**
* Write uint8.
* @param {Number} value
*/
writeU8(value) {
this.offset += 1;
this.ops.push(new NumberOp(U8, value));
return this;
}
/**
* Write uint16le.
* @param {Number} value
*/
writeU16(value) {
this.offset += 2;
this.ops.push(new NumberOp(U16, value));
return this;
}
/**
* Write uint16be.
* @param {Number} value
*/
writeU16BE(value) {
this.offset += 2;
this.ops.push(new NumberOp(U16BE, value));
return this;
}
/**
* Write uint24le.
* @param {Number} value
*/
writeU24(value) {
this.offset += 3;
this.ops.push(new NumberOp(U24, value));
return this;
}
/**
* Write uint24be.
* @param {Number} value
*/
writeU24BE(value) {
this.offset += 3;
this.ops.push(new NumberOp(U24BE, value));
return this;
}
/**
* Write uint32le.
* @param {Number} value
*/
writeU32(value) {
this.offset += 4;
this.ops.push(new NumberOp(U32, value));
return this;
}
/**
* Write uint32be.
* @param {Number} value
*/
writeU32BE(value) {
this.offset += 4;
this.ops.push(new NumberOp(U32BE, value));
return this;
}
/**
* Write uint40le.
* @param {Number} value
*/
writeU40(value) {
this.offset += 5;
this.ops.push(new NumberOp(U40, value));
return this;
}
/**
* Write uint40be.
* @param {Number} value
*/
writeU40BE(value) {
this.offset += 5;
this.ops.push(new NumberOp(U40BE, value));
return this;
}
/**
* Write uint48le.
* @param {Number} value
*/
writeU48(value) {
this.offset += 6;
this.ops.push(new NumberOp(U48, value));
return this;
}
/**
* Write uint48be.
* @param {Number} value
*/
writeU48BE(value) {
this.offset += 6;
this.ops.push(new NumberOp(U48BE, value));
return this;
}
/**
* Write uint56le.
* @param {Number} value
*/
writeU56(value) {
this.offset += 7;
this.ops.push(new NumberOp(U56, value));
return this;
}
/**
* Write uint56be.
* @param {Number} value
*/
writeU56BE(value) {
this.offset += 7;
this.ops.push(new NumberOp(U56BE, value));
return this;
}
/**
* Write uint64le.
* @param {Number} value
*/
writeU64(value) {
this.offset += 8;
this.ops.push(new NumberOp(U64, value));
return this;
}
/**
* Write uint64be.
* @param {Number} value
*/
writeU64BE(value) {
this.offset += 8;
this.ops.push(new NumberOp(U64BE, value));
return this;
}
/**
* Write int8.
* @param {Number} value
*/
writeI8(value) {
this.offset += 1;
this.ops.push(new NumberOp(I8, value));
return this;
}
/**
* Write int16le.
* @param {Number} value
*/
writeI16(value) {
this.offset += 2;
this.ops.push(new NumberOp(I16, value));
return this;
}
/**
* Write int16be.
* @param {Number} value
*/
writeI16BE(value) {
this.offset += 2;
this.ops.push(new NumberOp(I16BE, value));
return this;
}
/**
* Write int24le.
* @param {Number} value
*/
writeI24(value) {
this.offset += 3;
this.ops.push(new NumberOp(I24, value));
return this;
}
/**
* Write int24be.
* @param {Number} value
*/
writeI24BE(value) {
this.offset += 3;
this.ops.push(new NumberOp(I24BE, value));
return this;
}
/**
* Write int32le.
* @param {Number} value
*/
writeI32(value) {
this.offset += 4;
this.ops.push(new NumberOp(I32, value));
return this;
}
/**
* Write int32be.
* @param {Number} value
*/
writeI32BE(value) {
this.offset += 4;
this.ops.push(new NumberOp(I32BE, value));
return this;
}
/**
* Write int40le.
* @param {Number} value
*/
writeI40(value) {
this.offset += 5;
this.ops.push(new NumberOp(I40, value));
return this;
}
/**
* Write int40be.
* @param {Number} value
*/
writeI40BE(value) {
this.offset += 5;
this.ops.push(new NumberOp(I40BE, value));
return this;
}
/**
* Write int48le.
* @param {Number} value
*/
writeI48(value) {
this.offset += 6;
this.ops.push(new NumberOp(I48, value));
return this;
}
/**
* Write int48be.
* @param {Number} value
*/
writeI48BE(value) {
this.offset += 6;
this.ops.push(new NumberOp(I48BE, value));
return this;
}
/**
* Write int56le.
* @param {Number} value
*/
writeI56(value) {
this.offset += 7;
this.ops.push(new NumberOp(I56, value));
return this;
}
/**
* Write int56be.
* @param {Number} value
*/
writeI56BE(value) {
this.offset += 7;
this.ops.push(new NumberOp(I56BE, value));
return this;
}
/**
* Write int64le.
* @param {Number} value
*/
writeI64(value) {
this.offset += 8;
this.ops.push(new NumberOp(I64, value));
return this;
}
/**
* Write int64be.
* @param {Number} value
*/
writeI64BE(value) {
this.offset += 8;
this.ops.push(new NumberOp(I64BE, value));
return this;
}
/**
* Write float le.
* @param {Number} value
*/
writeFloat(value) {
this.offset += 4;
this.ops.push(new NumberOp(FL, value));
return this;
}
/**
* Write float be.
* @param {Number} value
*/
writeFloatBE(value) {
this.offset += 4;
this.ops.push(new NumberOp(FLBE, value));
return this;
}
/**
* Write double le.
* @param {Number} value
*/
writeDouble(value) {
this.offset += 8;
this.ops.push(new NumberOp(DBL, value));
return this;
}
/**
* Write double be.
* @param {Number} value
*/
writeDoubleBE(value) {
this.offset += 8;
this.ops.push(new NumberOp(DBLBE, value));
return this;
}
/**
* Write a varint.
* @param {Number} value
*/
writeVarint(value) {
this.offset += encoding.sizeVarint(value);
this.ops.push(new NumberOp(VARINT, value));
return this;
}
/**
* Write a varint (type 2).
* @param {Number} value
*/
writeVarint2(value) {
this.offset += encoding.sizeVarint2(value);
this.ops.push(new NumberOp(VARINT2, value));
return this;
}
/**
* Write bytes.
* @param {Buffer} value
*/
writeBytes(value) {
enforce(Buffer.isBuffer(value), 'value', 'buffer');
if (value.length === 0)
return this;
this.offset += value.length;
this.ops.push(new BufferOp(BYTES, value));
return this;
}
/**
* Write bytes with a varint length before them.
* @param {Buffer} value
*/
writeVarBytes(value) {
enforce(Buffer.isBuffer(value), 'value', 'buffer');
this.offset += encoding.sizeVarint(value.length);
this.ops.push(new NumberOp(VARINT, value.length));
if (value.length === 0)
return this;
this.offset += value.length;
this.ops.push(new BufferOp(BYTES, value));
return this;
}
/**
* Copy bytes.
* @param {Buffer} value
* @param {Number} start
* @param {Number} end
*/
copy(value, start, end) {
enforce(Buffer.isBuffer(value), 'value', 'buffer');
enforce((start >>> 0) === start, 'start', 'integer');
enforce((end >>> 0) === end, 'end', 'integer');
enforce(end >= start, 'start', 'integer');
const buf = value.slice(start, end);
this.writeBytes(buf);
return this;
}
/**
* Write string to buffer.
* @param {String} value
* @param {String?} enc - Any buffer-supported encoding.
*/
writeString(value, enc) {
if (enc == null)
enc = 'binary';
enforce(typeof value === 'string', 'value', 'string');
enforce(typeof enc === 'string', 'enc', 'string');
if (value.length === 0)
return this;
this.offset += Buffer.byteLength(value, enc);
this.ops.push(new StringOp(STR, value, enc));
return this;
}
/**
* Write a 32 byte hash.
* @param {Hash} value
*/
writeHash(value) {
if (typeof value !== 'string') {
enforce(Buffer.isBuffer(value), 'value', 'buffer');
enforce(value.length === 32, 'value', '32-byte hash');
this.writeBytes(value);
return this;
}
enforce(value.length === 64, 'value', '32-byte hash');
this.writeString(value, 'hex');
return this;
}
/**
* Write a string with a varint length before it.
* @param {String}
* @param {String?} enc - Any buffer-supported encoding.
*/
writeVarString(value, enc) {
if (enc == null)
enc = 'binary';
enforce(typeof value === 'string', 'value', 'string');
enforce(typeof enc === 'string', 'enc', 'string');
if (value.length === 0) {
this.ops.push(new NumberOp(VARINT, 0));
return this;
}
const size = Buffer.byteLength(value, enc);
this.offset += encoding.sizeVarint(size);
this.offset += size;
this.ops.push(new NumberOp(VARINT, size));
this.ops.push(new StringOp(STR, value, enc));
return this;
}
/**
* Write a null-terminated string.
* @param {String|Buffer}
* @param {String?} enc - Any buffer-supported encoding.
*/
writeNullString(value, enc) {
this.writeString(value, enc);
this.writeU8(0);
return this;
}
/**
* Calculate and write a checksum for the data written so far.
* @param {Function} hash
*/
writeChecksum(hash) {
if (hash && typeof hash.digest === 'function')
hash = hash.digest.bind(hash);
enforce(typeof hash === 'function', 'hash', 'function');
this.offset += 4;
this.ops.push(new FunctionOp(CHECKSUM, hash));
return this;
}
/**
* Fill N bytes with value.
* @param {Number} value
* @param {Number} size
*/
fill(value, size) {
enforce((value & 0xff) === value, 'value', 'byte');
enforce((size >>> 0) === size, 'size', 'integer');
if (size === 0)
return this;
this.offset += size;
this.ops.push(new FillOp(FILL, value, size));
return this;
}
}
/*
* Helpers
*/
class WriteOp {
constructor(type) {
this.type = type;
}
}
class NumberOp extends WriteOp {
constructor(type, value) {
super(type);
this.value = value;
}
}
class BufferOp extends WriteOp {
constructor(type, data) {
super(type);
this.data = data;
}
}
class StringOp extends WriteOp {
constructor(type, value, enc) {
super(type);
this.value = value;
this.enc = enc;
}
}
class FunctionOp extends WriteOp {
constructor(type, func) {
super(type);
this.func = func;
}
}
class FillOp extends WriteOp {
constructor(type, value, size) {
super(type);
this.value = value;
this.size = size;
}
}
/*
* Expose
*/
module.exports = BufferWriter;
}],
[/* 10 */ 'bufio', '/lib/staticwriter.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* staticwriter.js - buffer writer for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const enforce = __node_require__(6 /* './enforce' */);
const encoding = __node_require__(5 /* './encoding' */);
const EncodingError = __node_require__(7 /* './error' */);
/*
* Constants
*/
const EMPTY = Buffer.alloc(0);
const POOL_SIZE = 100 << 10;
let POOL = null;
/**
* Statically Allocated Writer
*/
class StaticWriter {
/**
* Statically allocated buffer writer.
* @constructor
* @param {Number|Buffer} options
*/
constructor(options) {
this.data = EMPTY;
this.offset = 0;
if (options != null)
this.init(options);
}
/**
* Assertion.
* @param {Number} size
*/
check(size) {
if (this.offset + size > this.data.length)
throw new EncodingError(this.offset, 'Out of bounds write', this.check);
}
/**
* Initialize options.
* @param {Object} options
*/
init(options) {
if (Buffer.isBuffer(options)) {
this.data = options;
this.offset = 0;
return this;
}
enforce((options >>> 0) === options, 'size', 'integer');
this.data = Buffer.allocUnsafeSlow(options);
this.offset = 0;
return this;
}
/**
* Allocate writer from preallocated 100kb pool.
* @param {Number} size
* @returns {StaticWriter}
*/
static pool(size) {
enforce((size >>> 0) === size, 'size', 'integer');
if (size <= POOL_SIZE) {
if (!POOL)
POOL = Buffer.allocUnsafeSlow(POOL_SIZE);
const bw = new StaticWriter();
bw.data = POOL.slice(0, size);
return bw;
}
return new StaticWriter(size);
}
/**
* Allocate and render the final buffer.
* @returns {Buffer} Rendered buffer.
*/
render() {
const {data, offset} = this;
if (offset !== data.length)
throw new EncodingError(offset, 'Out of bounds write');
this.destroy();
return data;
}
/**
* Slice the final buffer at written offset.
* @returns {Buffer} Rendered buffer.
*/
slice() {
const {data, offset} = this;
if (offset > data.length)
throw new EncodingError(offset, 'Out of bounds write');
this.destroy();
return data.slice(0, offset);
}
/**
* Get size of data written so far.
* @returns {Number}
*/
getSize() {
return this.offset;
}
/**
* Seek to relative offset.
* @param {Number} off
*/
seek(off) {
enforce(Number.isSafeInteger(off), 'off', 'integer');
if (this.offset + off < 0)
throw new EncodingError(this.offset, 'Out of bounds write');
this.check(off);
this.offset += off;
return this;
}
/**
* Destroy the buffer writer.
*/
destroy() {
this.data = EMPTY;
this.offset = 0;
return this;
}
/**
* Write uint8.
* @param {Number} value
*/
writeU8(value) {
this.check(1);
this.offset = encoding.writeU8(this.data, value, this.offset);
return this;
}
/**
* Write uint16le.
* @param {Number} value
*/
writeU16(value) {
this.check(2);
this.offset = encoding.writeU16(this.data, value, this.offset);
return this;
}
/**
* Write uint16be.
* @param {Number} value
*/
writeU16BE(value) {
this.check(2);
this.offset = encoding.writeU16BE(this.data, value, this.offset);
return this;
}
/**
* Write uint24le.
* @param {Number} value
*/
writeU24(value) {
this.check(3);
this.offset = encoding.writeU24(this.data, value, this.offset);
return this;
}
/**
* Write uint24be.
* @param {Number} value
*/
writeU24BE(value) {
this.check(3);
this.offset = encoding.writeU24BE(this.data, value, this.offset);
return this;
}
/**
* Write uint32le.
* @param {Number} value
*/
writeU32(value) {
this.check(4);
this.offset = encoding.writeU32(this.data, value, this.offset);
return this;
}
/**
* Write uint32be.
* @param {Number} value
*/
writeU32BE(value) {
this.check(4);
this.offset = encoding.writeU32BE(this.data, value, this.offset);
return this;
}
/**
* Write uint40le.
* @param {Number} value
*/
writeU40(value) {
this.check(5);
this.offset = encoding.writeU40(this.data, value, this.offset);
return this;
}
/**
* Write uint40be.
* @param {Number} value
*/
writeU40BE(value) {
this.check(5);
this.offset = encoding.writeU40BE(this.data, value, this.offset);
return this;
}
/**
* Write uint48le.
* @param {Number} value
*/
writeU48(value) {
this.check(6);
this.offset = encoding.writeU48(this.data, value, this.offset);
return this;
}
/**
* Write uint48be.
* @param {Number} value
*/
writeU48BE(value) {
this.check(6);
this.offset = encoding.writeU48BE(this.data, value, this.offset);
return this;
}
/**
* Write uint56le.
* @param {Number} value
*/
writeU56(value) {
this.check(7);
this.offset = encoding.writeU56(this.data, value, this.offset);
return this;
}
/**
* Write uint56be.
* @param {Number} value
*/
writeU56BE(value) {
this.check(7);
this.offset = encoding.writeU56BE(this.data, value, this.offset);
return this;
}
/**
* Write uint64le.
* @param {Number} value
*/
writeU64(value) {
this.check(8);
this.offset = encoding.writeU64(this.data, value, this.offset);
return this;
}
/**
* Write uint64be.
* @param {Number} value
*/
writeU64BE(value) {
this.check(8);
this.offset = encoding.writeU64BE(this.data, value, this.offset);
return this;
}
/**
* Write int8.
* @param {Number} value
*/
writeI8(value) {
this.check(1);
this.offset = encoding.writeI8(this.data, value, this.offset);
return this;
}
/**
* Write int16le.
* @param {Number} value
*/
writeI16(value) {
this.check(2);
this.offset = encoding.writeI16(this.data, value, this.offset);
return this;
}
/**
* Write int16be.
* @param {Number} value
*/
writeI16BE(value) {
this.check(2);
this.offset = encoding.writeI16BE(this.data, value, this.offset);
return this;
}
/**
* Write int24le.
* @param {Number} value
*/
writeI24(value) {
this.check(3);
this.offset = encoding.writeI24(this.data, value, this.offset);
return this;
}
/**
* Write int24be.
* @param {Number} value
*/
writeI24BE(value) {
this.check(3);
this.offset = encoding.writeI24BE(this.data, value, this.offset);
return this;
}
/**
* Write int32le.
* @param {Number} value
*/
writeI32(value) {
this.check(4);
this.offset = encoding.writeI32(this.data, value, this.offset);
return this;
}
/**
* Write int32be.
* @param {Number} value
*/
writeI32BE(value) {
this.check(4);
this.offset = encoding.writeI32BE(this.data, value, this.offset);
return this;
}
/**
* Write int40le.
* @param {Number} value
*/
writeI40(value) {
this.check(5);
this.offset = encoding.writeI40(this.data, value, this.offset);
return this;
}
/**
* Write int40be.
* @param {Number} value
*/
writeI40BE(value) {
this.check(5);
this.offset = encoding.writeI40BE(this.data, value, this.offset);
return this;
}
/**
* Write int48le.
* @param {Number} value
*/
writeI48(value) {
this.check(6);
this.offset = encoding.writeI48(this.data, value, this.offset);
return this;
}
/**
* Write int48be.
* @param {Number} value
*/
writeI48BE(value) {
this.check(6);
this.offset = encoding.writeI48BE(this.data, value, this.offset);
return this;
}
/**
* Write int56le.
* @param {Number} value
*/
writeI56(value) {
this.check(7);
this.offset = encoding.writeI56(this.data, value, this.offset);
return this;
}
/**
* Write int56be.
* @param {Number} value
*/
writeI56BE(value) {
this.check(7);
this.offset = encoding.writeI56BE(this.data, value, this.offset);
return this;
}
/**
* Write int64le.
* @param {Number} value
*/
writeI64(value) {
this.check(8);
this.offset = encoding.writeI64(this.data, value, this.offset);
return this;
}
/**
* Write int64be.
* @param {Number} value
*/
writeI64BE(value) {
this.check(8);
this.offset = encoding.writeI64BE(this.data, value, this.offset);
return this;
}
/**
* Write float le.
* @param {Number} value
*/
writeFloat(value) {
this.check(4);
this.offset = encoding.writeFloat(this.data, value, this.offset);
return this;
}
/**
* Write float be.
* @param {Number} value
*/
writeFloatBE(value) {
this.check(4);
this.offset = encoding.writeFloatBE(this.data, value, this.offset);
return this;
}
/**
* Write double le.
* @param {Number} value
*/
writeDouble(value) {
this.check(8);
this.offset = encoding.writeDouble(this.data, value, this.offset);
return this;
}
/**
* Write double be.
* @param {Number} value
*/
writeDoubleBE(value) {
this.check(8);
this.offset = encoding.writeDoubleBE(this.data, value, this.offset);
return this;
}
/**
* Write a varint.
* @param {Number} value
*/
writeVarint(value) {
this.offset = encoding.writeVarint(this.data, value, this.offset);
return this;
}
/**
* Write a varint (type 2).
* @param {Number} value
*/
writeVarint2(value) {
this.offset = encoding.writeVarint2(this.data, value, this.offset);
return this;
}
/**
* Write bytes.
* @param {Buffer} value
*/
writeBytes(value) {
enforce(Buffer.isBuffer(value), 'value', 'buffer');
this.check(value.length);
this.offset += value.copy(this.data, this.offset);
return this;
}
/**
* Write bytes with a varint length before them.
* @param {Buffer} value
*/
writeVarBytes(value) {
enforce(Buffer.isBuffer(value), 'value', 'buffer');
this.writeVarint(value.length);
this.writeBytes(value);
return this;
}
/**
* Copy bytes.
* @param {Buffer} value
* @param {Number} start
* @param {Number} end
*/
copy(value, start, end) {
enforce(Buffer.isBuffer(value), 'value', 'buffer');
enforce((start >>> 0) === start, 'start', 'integer');
enforce((end >>> 0) === end, 'end', 'integer');
enforce(end >= start, 'start', 'integer');
this.check(end - start);
this.offset += value.copy(this.data, this.offset, start, end);
return this;
}
/**
* Write string to buffer.
* @param {String} value
* @param {String?} enc - Any buffer-supported encoding.
*/
writeString(value, enc) {
if (enc == null)
enc = 'binary';
enforce(typeof value === 'string', 'value', 'string');
enforce(typeof enc === 'string', 'enc', 'string');
if (value.length === 0)
return this;
const size = Buffer.byteLength(value, enc);
this.check(size);
this.offset += this.data.write(value, this.offset, enc);
return this;
}
/**
* Write a 32 byte hash.
* @param {Hash} value
*/
writeHash(value) {
if (typeof value !== 'string') {
enforce(Buffer.isBuffer(value), 'value', 'buffer');
enforce(value.length === 32, 'value', '32-byte hash');
this.writeBytes(value);
return this;
}
enforce(value.length === 64, 'value', '32-byte hash');
this.check(32);
this.offset += this.data.write(value, this.offset, 'hex');
return this;
}
/**
* Write a string with a varint length before it.
* @param {String}
* @param {String?} enc - Any buffer-supported encoding.
*/
writeVarString(value, enc) {
if (enc == null)
enc = 'binary';
enforce(typeof value === 'string', 'value', 'string');
enforce(typeof enc === 'string', 'enc', 'string');
if (value.length === 0) {
this.writeVarint(0);
return this;
}
const size = Buffer.byteLength(value, enc);
this.writeVarint(size);
this.check(size);
this.offset += this.data.write(value, this.offset, enc);
return this;
}
/**
* Write a null-terminated string.
* @param {String|Buffer}
* @param {String?} enc - Any buffer-supported encoding.
*/
writeNullString(value, enc) {
this.writeString(value, enc);
this.writeU8(0);
return this;
}
/**
* Calculate and write a checksum for the data written so far.
* @param {Function} hash
*/
writeChecksum(hash) {
if (!hash || typeof hash.digest !== 'function')
enforce(typeof hash === 'function', 'hash', 'function');
this.check(4);
const data = this.data.slice(0, this.offset);
const raw = hash.digest ? hash.digest(data) : hash(data);
raw.copy(this.data, this.offset, 0, 4);
this.offset += 4;
return this;
}
/**
* Fill N bytes with value.
* @param {Number} value
* @param {Number} size
*/
fill(value, size) {
enforce((value & 0xff) === value, 'value', 'byte');
enforce((size >>> 0) === size, 'size', 'integer');
this.check(size);
this.data.fill(value, this.offset, this.offset + size);
this.offset += size;
return this;
}
}
/*
* Expose
*/
module.exports = StaticWriter;
}],
[/* 11 */ 'bufio', '/lib/struct.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* struct.js - struct object for bcoin
* Copyright (c) 2018, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const enforce = __node_require__(6 /* './enforce' */);
const BufferReader = __node_require__(8 /* './reader' */);
const BufferWriter = __node_require__(9 /* './writer' */);
const StaticWriter = __node_require__(10 /* './staticwriter' */);
const {custom} = __node_require__(4 /* './custom' */);
/**
* Struct
*/
class Struct {
constructor() {}
inject(obj) {
enforce(obj instanceof this.constructor, 'obj', 'struct');
return this.decode(obj.encode());
}
clone() {
const copy = new this.constructor();
return copy.inject(this);
}
/*
* Bindable
*/
getSize(extra) {
return -1;
}
write(bw, extra) {
return bw;
}
read(br, extra) {
return this;
}
toString() {
return Object.prototype.toString.call(this);
}
fromString(str, extra) {
return this;
}
getJSON() {
return this;
}
fromJSON(json, extra) {
return this;
}
fromOptions(options, extra) {
return this;
}
from(options, extra) {
return this.fromOptions(options, extra);
}
format() {
return this.getJSON();
}
/*
* API
*/
encode(extra) {
const size = this.getSize(extra);
const bw = size === -1
? new BufferWriter()
: new StaticWriter(size);
this.write(bw, extra);
return bw.render();
}
decode(data, extra) {
const br = new BufferReader(data);
this.read(br, extra);
return this;
}
toHex(extra) {
return this.encode(extra).toString('hex');
}
fromHex(str, extra) {
enforce(typeof str === 'string', 'str', 'string');
const size = str.length >>> 1;
const data = Buffer.from(str, 'hex');
if (data.length !== size)
throw new Error('Invalid hex string.');
return this.decode(data, extra);
}
toBase64(extra) {
return this.encode(extra).toString('base64');
}
fromBase64(str, extra) {
enforce(typeof str === 'string', 'str', 'string');
const data = Buffer.from(str, 'base64');
if (str.length > size64(data.length))
throw new Error('Invalid base64 string.');
return this.decode(data, extra);
}
toJSON() {
return this.getJSON();
}
[custom]() {
return this.format();
}
/*
* Static API
*/
static read(br, extra) {
return new this().read(br, extra);
}
static decode(data, extra) {
return new this().decode(data, extra);
}
static fromHex(str, extra) {
return new this().fromHex(str, extra);
}
static fromBase64(str, extra) {
return new this().fromBase64(str, extra);
}
static fromString(str, extra) {
return new this().fromString(str, extra);
}
static fromJSON(json, extra) {
return new this().fromJSON(json, extra);
}
static fromOptions(options, extra) {
return new this().fromOptions(options, extra);
}
static from(options, extra) {
return new this().from(options, extra);
}
/*
* Aliases
*/
toWriter(bw, extra) {
return this.write(bw, extra);
}
fromReader(br, extra) {
return this.read(br, extra);
}
toRaw(extra) {
return this.encode(extra);
}
fromRaw(data, extra) {
return this.decode(data, extra);
}
/*
* Static Aliases
*/
static fromReader(br, extra) {
return this.read(br, extra);
}
static fromRaw(data, extra) {
return this.decode(data, extra);
}
}
/*
* Helpers
*/
function size64(size) {
const expect = ((4 * size / 3) + 3) & ~3;
return expect >>> 0;
}
/*
* Expose
*/
module.exports = Struct;
}],
[/* 12 */ 'bcrypto', '/lib/encoding/base58-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* base58.js - base58 for bcrypto
* Copyright (c) 2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(13 /* '../js/base58' */);
}],
[/* 13 */ 'bcrypto', '/lib/js/base58.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* base58.js - base58 for bcrypto
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on bitcoin/bitcoin:
* Copyright (c) 2009-2019, The Bitcoin Core Developers (MIT License).
* Copyright (c) 2009-2019, The Bitcoin Developers (MIT License).
* https://github.com/bitcoin/bitcoin
*
* Resources:
* https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
/*
* Constants
*/
const CHARSET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
const TABLE = [
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6,
7, 8, -1, -1, -1, -1, -1, -1,
-1, 9, 10, 11, 12, 13, 14, 15,
16, -1, 17, 18, 19, 20, 21, -1,
22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, -1, -1, -1, -1, -1,
-1, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, -1, 44, 45, 46,
47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, -1, -1, -1, -1, -1
];
const pool = Buffer.alloc(128);
/**
* Encode a base58 string.
* @param {Buffer} data
* @returns {String}
*/
function encode(data) {
assert(Buffer.isBuffer(data));
let zeroes = 0;
let i = 0;
for (; i < data.length; i++) {
if (data[i] !== 0)
break;
zeroes += 1;
}
const size = (((data.length - zeroes) * 138 / 100) | 0) + 1;
const b58 = size <= 128 ? pool.fill(0) : Buffer.alloc(size);
let length = 0;
for (; i < data.length; i++) {
let carry = data[i];
let j = 0;
for (let k = size - 1; k >= 0; k--, j++) {
if (carry === 0 && j >= length)
break;
carry += b58[k] * 256;
b58[k] = carry % 58;
carry = (carry / 58) | 0;
}
assert(carry === 0);
length = j;
}
i = size - length;
while (i < size && b58[i] === 0)
i += 1;
let str = '';
for (let j = 0; j < zeroes; j++)
str += '1';
while (i < size)
str += CHARSET[b58[i++]];
return str;
}
/**
* Decode a base58 string.
* @param {String} str
* @returns {Buffer}
* @throws on non-base58 character.
*/
function decode(str) {
assert(typeof str === 'string');
let zeroes = 0;
let i = 0;
for (; i < str.length; i++) {
if (str[i] !== '1')
break;
zeroes += 1;
}
const size = ((str.length * 733) / 1000 | 0) + 1;
const b256 = size <= 128 ? pool.fill(0) : Buffer.alloc(size);
let length = 0;
for (; i < str.length; i++) {
const ch = str.charCodeAt(i);
if (ch & 0xff80)
throw new Error('Invalid base58 string.');
const val = TABLE[ch];
if (val === -1)
throw new Error('Invalid base58 string.');
let carry = val;
let j = 0;
for (let k = size - 1; k >= 0; k--, j++) {
if (carry === 0 && j >= length)
break;
carry += b256[k] * 58;
b256[k] = carry;
carry >>>= 8;
}
assert(carry === 0);
length = j;
}
// See: https://github.com/bitcoin/bitcoin/commit/2bcf1fc4
i = size - length;
const out = Buffer.alloc(zeroes + (size - i));
let j;
for (j = 0; j < zeroes; j++)
out[j] = 0;
while (i < size)
out[j++] = b256[i++];
return out;
}
/**
* Test whether the string is a base58 string.
* @param {String} str
* @returns {Buffer}
*/
function test(str) {
assert(typeof str === 'string');
for (let i = 0; i < str.length; i++) {
const ch = str.charCodeAt(i);
if (ch & 0xff80)
return false;
if (TABLE[ch] === -1)
return false;
}
return true;
}
/*
* Expose
*/
exports.native = 0;
exports.encode = encode;
exports.decode = decode;
exports.test = test;
}],
[/* 14 */ 'bcrypto', '/lib/internal/assert.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* assert.js - assert for bcrypto
* Copyright (c) 2020, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
/*
* Assert
*/
function assert(val, msg) {
if (!val) {
const err = new Error(msg || 'Assertion failed');
if (Error.captureStackTrace)
Error.captureStackTrace(err, assert);
throw err;
}
}
/*
* Expose
*/
module.exports = assert;
}],
[/* 15 */ 'bcrypto', '/lib/sha512-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* sha512.js - sha512 for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(16 /* './js/sha512' */);
}],
[/* 16 */ 'bcrypto', '/lib/js/sha512.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* sha512.js - SHA512 implementation for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on indutny/hash.js:
* Copyright (c) 2014, Fedor Indutny (MIT License).
* https://github.com/indutny/hash.js
*
* Resources:
* https://en.wikipedia.org/wiki/SHA-2
* https://tools.ietf.org/html/rfc4634
* https://github.com/indutny/hash.js/blob/master/lib/hash/sha/512.js
*/
/* eslint camelcase: "off" */
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const HMAC = __node_require__(17 /* '../internal/hmac' */);
/*
* Constants
*/
const FINALIZED = -1;
const DESC = Buffer.alloc(16, 0x00);
const PADDING = Buffer.alloc(128, 0x00);
PADDING[0] = 0x80;
const K = new Uint32Array([
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
]);
/**
* SHA512
*/
class SHA512 {
constructor() {
this.state = new Uint32Array(16);
this.msg = new Uint32Array(160);
this.block = Buffer.alloc(128);
this.size = FINALIZED;
}
init() {
this.state[0] = 0x6a09e667;
this.state[1] = 0xf3bcc908;
this.state[2] = 0xbb67ae85;
this.state[3] = 0x84caa73b;
this.state[4] = 0x3c6ef372;
this.state[5] = 0xfe94f82b;
this.state[6] = 0xa54ff53a;
this.state[7] = 0x5f1d36f1;
this.state[8] = 0x510e527f;
this.state[9] = 0xade682d1;
this.state[10] = 0x9b05688c;
this.state[11] = 0x2b3e6c1f;
this.state[12] = 0x1f83d9ab;
this.state[13] = 0xfb41bd6b;
this.state[14] = 0x5be0cd19;
this.state[15] = 0x137e2179;
this.size = 0;
return this;
}
update(data) {
assert(Buffer.isBuffer(data));
this._update(data, data.length);
return this;
}
final() {
return this._final(Buffer.alloc(64));
}
_update(data, len) {
assert(this.size !== FINALIZED, 'Context is not initialized.');
let pos = this.size & 127;
let off = 0;
this.size += len;
if (pos > 0) {
let want = 128 - pos;
if (want > len)
want = len;
data.copy(this.block, pos, off, off + want);
pos += want;
len -= want;
off += want;
if (pos < 128)
return;
this._transform(this.block, 0);
}
while (len >= 128) {
this._transform(data, off);
off += 128;
len -= 128;
}
if (len > 0)
data.copy(this.block, 0, off, off + len);
}
/**
* Finalize SHA512 context.
* @private
* @param {Buffer} out
* @returns {Buffer}
*/
_final(out) {
assert(this.size !== FINALIZED, 'Context is not initialized.');
const pos = this.size & 127;
const len = this.size * 8;
writeU32(DESC, (len * (1 / 0x100000000)) >>> 0, 8);
writeU32(DESC, len >>> 0, 12);
this._update(PADDING, 1 + ((239 - pos) & 127));
this._update(DESC, 16);
for (let i = 0; i < 16; i++) {
writeU32(out, this.state[i], i * 4);
this.state[i] = 0;
}
for (let i = 0; i < 160; i++)
this.msg[i] = 0;
for (let i = 0; i < 128; i++)
this.block[i] = 0;
this.size = FINALIZED;
return out;
}
_prepare(chunk, pos) {
const W = this.msg;
let i = 0;
for (; i < 32; i++)
W[i] = readU32(chunk, pos + i * 4);
for (; i < 160; i += 2) {
const c0_hi = g1_512_hi(W[i - 4], W[i - 3]);
const c0_lo = g1_512_lo(W[i - 4], W[i - 3]);
const c1_hi = W[i - 14];
const c1_lo = W[i - 13];
const c2_hi = g0_512_hi(W[i - 30], W[i - 29]);
const c2_lo = g0_512_lo(W[i - 30], W[i - 29]);
const c3_hi = W[i - 32];
const c3_lo = W[i - 31];
W[i + 0] = sum64_4_hi(c0_hi, c0_lo,
c1_hi, c1_lo,
c2_hi, c2_lo,
c3_hi, c3_lo);
W[i + 1] = sum64_4_lo(c0_hi, c0_lo,
c1_hi, c1_lo,
c2_hi, c2_lo,
c3_hi, c3_lo);
}
}
_transform(chunk, pos) {
const W = this.msg;
this._prepare(chunk, pos);
let ah = this.state[0];
let al = this.state[1];
let bh = this.state[2];
let bl = this.state[3];
let ch = this.state[4];
let cl = this.state[5];
let dh = this.state[6];
let dl = this.state[7];
let eh = this.state[8];
let el = this.state[9];
let fh = this.state[10];
let fl = this.state[11];
let gh = this.state[12];
let gl = this.state[13];
let hh = this.state[14];
let hl = this.state[15];
for (let i = 0; i < W.length; i += 2) {
let c0_hi = hh;
let c0_lo = hl;
let c1_hi = s1_512_hi(eh, el);
let c1_lo = s1_512_lo(eh, el);
const c2_hi = ch64_hi(eh, el, fh, fl, gh, gl);
const c2_lo = ch64_lo(eh, el, fh, fl, gh, gl);
const c3_hi = K[i + 0];
const c3_lo = K[i + 1];
const c4_hi = W[i + 0];
const c4_lo = W[i + 1];
const T1_hi = sum64_5_hi(c0_hi, c0_lo,
c1_hi, c1_lo,
c2_hi, c2_lo,
c3_hi, c3_lo,
c4_hi, c4_lo);
const T1_lo = sum64_5_lo(c0_hi, c0_lo,
c1_hi, c1_lo,
c2_hi, c2_lo,
c3_hi, c3_lo,
c4_hi, c4_lo);
c0_hi = s0_512_hi(ah, al);
c0_lo = s0_512_lo(ah, al);
c1_hi = maj64_hi(ah, al, bh, bl, ch, cl);
c1_lo = maj64_lo(ah, al, bh, bl, ch, cl);
const T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo);
const T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo);
hh = gh;
hl = gl;
gh = fh;
gl = fl;
fh = eh;
fl = el;
eh = sum64_hi(dh, dl, T1_hi, T1_lo);
el = sum64_lo(dl, dl, T1_hi, T1_lo);
dh = ch;
dl = cl;
ch = bh;
cl = bl;
bh = ah;
bl = al;
ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo);
al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo);
}
sum64(this.state, 0, ah, al);
sum64(this.state, 2, bh, bl);
sum64(this.state, 4, ch, cl);
sum64(this.state, 6, dh, dl);
sum64(this.state, 8, eh, el);
sum64(this.state, 10, fh, fl);
sum64(this.state, 12, gh, gl);
sum64(this.state, 14, hh, hl);
}
static hash() {
return new SHA512();
}
static hmac() {
return new HMAC(SHA512, 128);
}
static digest(data) {
return SHA512.ctx.init().update(data).final();
}
static root(left, right) {
assert(Buffer.isBuffer(left) && left.length === 64);
assert(Buffer.isBuffer(right) && right.length === 64);
return SHA512.ctx.init().update(left).update(right).final();
}
static multi(x, y, z) {
const {ctx} = SHA512;
ctx.init();
ctx.update(x);
ctx.update(y);
if (z)
ctx.update(z);
return ctx.final();
}
static mac(data, key) {
return SHA512.hmac().init(key).update(data).final();
}
}
/*
* Static
*/
SHA512.native = 0;
SHA512.id = 'SHA512';
SHA512.size = 64;
SHA512.bits = 512;
SHA512.blockSize = 128;
SHA512.zero = Buffer.alloc(64, 0x00);
SHA512.ctx = new SHA512();
/*
* Helpers
*/
function sum64(buf, pos, ah, al) {
const bh = buf[pos + 0];
const bl = buf[pos + 1];
const lo = (al + bl) >>> 0;
const hi = (lo < al) + ah + bh;
buf[pos + 0] = hi >>> 0;
buf[pos + 1] = lo;
}
function sum64_hi(ah, al, bh, bl) {
const lo = (al + bl) >>> 0;
const hi = (lo < al) + ah + bh;
return hi >>> 0;
}
function sum64_lo(ah, al, bh, bl) {
const lo = al + bl;
return lo >>> 0;
}
function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) {
let carry = 0;
let lo = al;
lo = (lo + bl) >>> 0;
carry += (lo < al);
lo = (lo + cl) >>> 0;
carry += (lo < cl);
lo = (lo + dl) >>> 0;
carry += (lo < dl);
const hi = ah + bh + ch + dh + carry;
return hi >>> 0;
}
function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) {
const lo = al + bl + cl + dl;
return lo >>> 0;
}
function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
let carry = 0;
let lo = al;
lo = (lo + bl) >>> 0;
carry += (lo < al);
lo = (lo + cl) >>> 0;
carry += (lo < cl);
lo = (lo + dl) >>> 0;
carry += (lo < dl);
lo = (lo + el) >>> 0;
carry += (lo < el);
const hi = ah + bh + ch + dh + eh + carry;
return hi >>> 0;
}
function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
const lo = al + bl + cl + dl + el;
return lo >>> 0;
}
function rotr64_hi(ah, al, num) {
const r = (al << (32 - num)) | (ah >>> num);
return r >>> 0;
}
function rotr64_lo(ah, al, num) {
const r = (ah << (32 - num)) | (al >>> num);
return r >>> 0;
}
function shr64_hi(ah, al, num) {
return ah >>> num;
}
function shr64_lo(ah, al, num) {
const r = (ah << (32 - num)) | (al >>> num);
return r >>> 0;
}
function ch64_hi(xh, xl, yh, yl, zh, zl) {
const r = (xh & yh) ^ ((~xh) & zh);
return r >>> 0;
}
function ch64_lo(xh, xl, yh, yl, zh, zl) {
const r = (xl & yl) ^ ((~xl) & zl);
return r >>> 0;
}
function maj64_hi(xh, xl, yh, yl, zh, zl) {
const r = (xh & yh) ^ (xh & zh) ^ (yh & zh);
return r >>> 0;
}
function maj64_lo(xh, xl, yh, yl, zh, zl) {
const r = (xl & yl) ^ (xl & zl) ^ (yl & zl);
return r >>> 0;
}
function s0_512_hi(xh, xl) {
const c0_hi = rotr64_hi(xh, xl, 28);
const c1_hi = rotr64_hi(xl, xh, 2); // 34
const c2_hi = rotr64_hi(xl, xh, 7); // 39
const r = c0_hi ^ c1_hi ^ c2_hi;
return r >>> 0;
}
function s0_512_lo(xh, xl) {
const c0_lo = rotr64_lo(xh, xl, 28);
const c1_lo = rotr64_lo(xl, xh, 2); // 34
const c2_lo = rotr64_lo(xl, xh, 7); // 39
const r = c0_lo ^ c1_lo ^ c2_lo;
return r >>> 0;
}
function s1_512_hi(xh, xl) {
const c0_hi = rotr64_hi(xh, xl, 14);
const c1_hi = rotr64_hi(xh, xl, 18);
const c2_hi = rotr64_hi(xl, xh, 9); // 41
const r = c0_hi ^ c1_hi ^ c2_hi;
return r >>> 0;
}
function s1_512_lo(xh, xl) {
const c0_lo = rotr64_lo(xh, xl, 14);
const c1_lo = rotr64_lo(xh, xl, 18);
const c2_lo = rotr64_lo(xl, xh, 9); // 41
const r = c0_lo ^ c1_lo ^ c2_lo;
return r >>> 0;
}
function g0_512_hi(xh, xl) {
const c0_hi = rotr64_hi(xh, xl, 1);
const c1_hi = rotr64_hi(xh, xl, 8);
const c2_hi = shr64_hi(xh, xl, 7);
const r = c0_hi ^ c1_hi ^ c2_hi;
return r >>> 0;
}
function g0_512_lo(xh, xl) {
const c0_lo = rotr64_lo(xh, xl, 1);
const c1_lo = rotr64_lo(xh, xl, 8);
const c2_lo = shr64_lo(xh, xl, 7);
const r = c0_lo ^ c1_lo ^ c2_lo;
return r >>> 0;
}
function g1_512_hi(xh, xl) {
const c0_hi = rotr64_hi(xh, xl, 19);
const c1_hi = rotr64_hi(xl, xh, 29); // 61
const c2_hi = shr64_hi(xh, xl, 6);
const r = c0_hi ^ c1_hi ^ c2_hi;
return r >>> 0;
}
function g1_512_lo(xh, xl) {
const c0_lo = rotr64_lo(xh, xl, 19);
const c1_lo = rotr64_lo(xl, xh, 29); // 61
const c2_lo = shr64_lo(xh, xl, 6);
const r = c0_lo ^ c1_lo ^ c2_lo;
return r >>> 0;
}
function readU32(data, off) {
return (data[off++] * 0x1000000
+ data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function writeU32(data, num, off) {
data[off++] = num >>> 24;
data[off++] = num >>> 16;
data[off++] = num >>> 8;
data[off++] = num;
return off;
}
/*
* Expose
*/
module.exports = SHA512;
}],
[/* 17 */ 'bcrypto', '/lib/internal/hmac.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* hmac.js - hmac for bcrypto
* Copyright (c) 2016-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on indutny/hash.js:
* Copyright (c) 2014, Fedor Indutny (MIT License).
* https://github.com/indutny/hash.js
*
* Resources:
* https://en.wikipedia.org/wiki/HMAC
* https://tools.ietf.org/html/rfc2104
* https://github.com/indutny/hash.js/blob/master/lib/hash/hmac.js
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
/**
* HMAC
*/
class HMAC {
/**
* Create an HMAC.
* @param {Function} Hash
* @param {Number} size
* @param {Array} [x=[]]
* @param {Array} [y=[]]
*/
constructor(Hash, size, x = [], y = []) {
assert(typeof Hash === 'function');
assert((size >>> 0) === size);
assert(Array.isArray(x));
assert(Array.isArray(y));
this.hash = Hash;
this.size = size;
this.x = x;
this.y = y;
this.inner = new Hash();
this.outer = new Hash();
}
/**
* Initialize HMAC context.
* @param {Buffer} data
*/
init(key) {
assert(Buffer.isBuffer(key));
// Shorten key
if (key.length > this.size) {
const Hash = this.hash;
const h = new Hash();
h.init(...this.x);
h.update(key);
key = h.final(...this.y);
assert(key.length <= this.size);
}
// Pad key
const pad = Buffer.alloc(this.size);
for (let i = 0; i < key.length; i++)
pad[i] = key[i] ^ 0x36;
for (let i = key.length; i < pad.length; i++)
pad[i] = 0x36;
this.inner.init(...this.x);
this.inner.update(pad);
for (let i = 0; i < key.length; i++)
pad[i] = key[i] ^ 0x5c;
for (let i = key.length; i < pad.length; i++)
pad[i] = 0x5c;
this.outer.init(...this.x);
this.outer.update(pad);
return this;
}
/**
* Update HMAC context.
* @param {Buffer} data
*/
update(data) {
this.inner.update(data);
return this;
}
/**
* Finalize HMAC context.
* @returns {Buffer}
*/
final() {
this.outer.update(this.inner.final(...this.y));
return this.outer.final(...this.y);
}
}
/*
* Expose
*/
module.exports = HMAC;
}],
[/* 18 */ 'bcrypto', '/lib/hash160-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* hash160.js - hash160 for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(19 /* './js/hash160' */);
}],
[/* 19 */ 'bcrypto', '/lib/js/hash160.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* hash160.js - Hash160 implementation for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Resources:
* https://github.com/bitcoin/bitcoin/blob/master/src/hash.h
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const SHA256 = __node_require__(20 /* './sha256' */);
const RIPEMD160 = __node_require__(21 /* './ripemd160' */);
const HMAC = __node_require__(17 /* '../internal/hmac' */);
/*
* Constants
*/
const rmd = new RIPEMD160();
/**
* Hash160
*/
class Hash160 {
constructor() {
this.ctx = new SHA256();
}
init() {
this.ctx.init();
return this;
}
update(data) {
this.ctx.update(data);
return this;
}
final() {
const out = Buffer.alloc(32);
this.ctx._final(out);
rmd.init();
rmd.update(out);
rmd._final(out);
return out.slice(0, 20);
}
static hash() {
return new Hash160();
}
static hmac() {
return new HMAC(Hash160, 64);
}
static digest(data) {
return Hash160.ctx.init().update(data).final();
}
static root(left, right) {
assert(Buffer.isBuffer(left) && left.length === 20);
assert(Buffer.isBuffer(right) && right.length === 20);
return Hash160.ctx.init().update(left).update(right).final();
}
static multi(x, y, z) {
const {ctx} = Hash160;
ctx.init();
ctx.update(x);
ctx.update(y);
if (z)
ctx.update(z);
return ctx.final();
}
static mac(data, key) {
return Hash160.hmac().init(key).update(data).final();
}
}
/*
* Static
*/
Hash160.native = 0;
Hash160.id = 'HASH160';
Hash160.size = 20;
Hash160.bits = 160;
Hash160.blockSize = 64;
Hash160.zero = Buffer.alloc(20, 0x00);
Hash160.ctx = new Hash160();
/*
* Expose
*/
module.exports = Hash160;
}],
[/* 20 */ 'bcrypto', '/lib/js/sha256.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* sha256.js - SHA256 implementation for bcrypto
* Copyright (c) 2016-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on indutny/hash.js:
* Copyright (c) 2014, Fedor Indutny (MIT License).
* https://github.com/indutny/hash.js
*
* Resources:
* https://en.wikipedia.org/wiki/SHA-2
* https://tools.ietf.org/html/rfc4634
* https://github.com/indutny/hash.js/blob/master/lib/hash/sha/256.js
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const HMAC = __node_require__(17 /* '../internal/hmac' */);
/*
* Constants
*/
const FINALIZED = -1;
const DESC = Buffer.alloc(8, 0x00);
const PADDING = Buffer.alloc(64, 0x00);
PADDING[0] = 0x80;
const K = new Uint32Array([
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]);
/**
* SHA256
*/
class SHA256 {
constructor() {
this.state = new Uint32Array(8);
this.msg = new Uint32Array(64);
this.block = Buffer.alloc(64);
this.size = FINALIZED;
}
init() {
this.state[0] = 0x6a09e667;
this.state[1] = 0xbb67ae85;
this.state[2] = 0x3c6ef372;
this.state[3] = 0xa54ff53a;
this.state[4] = 0x510e527f;
this.state[5] = 0x9b05688c;
this.state[6] = 0x1f83d9ab;
this.state[7] = 0x5be0cd19;
this.size = 0;
return this;
}
update(data) {
assert(Buffer.isBuffer(data));
this._update(data, data.length);
return this;
}
final() {
return this._final(Buffer.alloc(32));
}
_update(data, len) {
assert(this.size !== FINALIZED, 'Context is not initialized.');
let pos = this.size & 63;
let off = 0;
this.size += len;
if (pos > 0) {
let want = 64 - pos;
if (want > len)
want = len;
data.copy(this.block, pos, off, off + want);
pos += want;
len -= want;
off += want;
if (pos < 64)
return;
this._transform(this.block, 0);
}
while (len >= 64) {
this._transform(data, off);
off += 64;
len -= 64;
}
if (len > 0)
data.copy(this.block, 0, off, off + len);
}
_final(out) {
assert(this.size !== FINALIZED, 'Context is not initialized.');
const pos = this.size & 63;
const len = this.size * 8;
writeU32(DESC, (len * (1 / 0x100000000)) >>> 0, 0);
writeU32(DESC, len >>> 0, 4);
this._update(PADDING, 1 + ((119 - pos) & 63));
this._update(DESC, 8);
for (let i = 0; i < 8; i++) {
writeU32(out, this.state[i], i * 4);
this.state[i] = 0;
}
for (let i = 0; i < 64; i++)
this.msg[i] = 0;
for (let i = 0; i < 64; i++)
this.block[i] = 0;
this.size = FINALIZED;
return out;
}
_transform(chunk, pos) {
const W = this.msg;
let a = this.state[0];
let b = this.state[1];
let c = this.state[2];
let d = this.state[3];
let e = this.state[4];
let f = this.state[5];
let g = this.state[6];
let h = this.state[7];
let i = 0;
for (; i < 16; i++)
W[i] = readU32(chunk, pos + i * 4);
for (; i < 64; i++)
W[i] = sigma1(W[i - 2]) + W[i - 7] + sigma0(W[i - 15]) + W[i - 16];
for (i = 0; i < 64; i++) {
const t1 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];
const t2 = Sigma0(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = (d + t1) >>> 0;
d = c;
c = b;
b = a;
a = (t1 + t2) >>> 0;
}
this.state[0] += a;
this.state[1] += b;
this.state[2] += c;
this.state[3] += d;
this.state[4] += e;
this.state[5] += f;
this.state[6] += g;
this.state[7] += h;
}
static hash() {
return new SHA256();
}
static hmac() {
return new HMAC(SHA256, 64);
}
static digest(data) {
return SHA256.ctx.init().update(data).final();
}
static root(left, right) {
assert(Buffer.isBuffer(left) && left.length === 32);
assert(Buffer.isBuffer(right) && right.length === 32);
return SHA256.ctx.init().update(left).update(right).final();
}
static multi(x, y, z) {
const {ctx} = SHA256;
ctx.init();
ctx.update(x);
ctx.update(y);
if (z)
ctx.update(z);
return ctx.final();
}
static mac(data, key) {
return SHA256.hmac().init(key).update(data).final();
}
}
/*
* Static
*/
SHA256.native = 0;
SHA256.id = 'SHA256';
SHA256.size = 32;
SHA256.bits = 256;
SHA256.blockSize = 64;
SHA256.zero = Buffer.alloc(32, 0x00);
SHA256.ctx = new SHA256();
/*
* Helpers
*/
function Sigma0(x) {
return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10);
}
function Sigma1(x) {
return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7);
}
function sigma0(x) {
return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3);
}
function sigma1(x) {
return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10);
}
function Ch(x, y, z) {
return z ^ (x & (y ^ z));
}
function Maj(x, y, z) {
return (x & y) | (z & (x | y));
}
function readU32(data, off) {
return (data[off++] * 0x1000000
+ data[off++] * 0x10000
+ data[off++] * 0x100
+ data[off]);
}
function writeU32(data, num, off) {
data[off++] = num >>> 24;
data[off++] = num >>> 16;
data[off++] = num >>> 8;
data[off++] = num;
return off;
}
/*
* Expose
*/
module.exports = SHA256;
}],
[/* 21 */ 'bcrypto', '/lib/js/ripemd160.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* ripemd160.js - RIPEMD160 implementation for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on indutny/hash.js:
* Copyright (c) 2014, Fedor Indutny (MIT License).
* https://github.com/indutny/hash.js
*
* Resources:
* https://en.wikipedia.org/wiki/RIPEMD-160
* https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
* https://github.com/indutny/hash.js/blob/master/lib/hash/ripemd.js
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const HMAC = __node_require__(17 /* '../internal/hmac' */);
/*
* Constants
*/
const FINALIZED = -1;
const DESC = Buffer.alloc(8, 0x00);
const PADDING = Buffer.alloc(64, 0x00);
PADDING[0] = 0x80;
const r = new Uint8Array([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
]);
const rh = new Uint8Array([
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
]);
const s = new Uint8Array([
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
]);
const sh = new Uint8Array([
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
]);
/**
* RIPEMD160
*/
class RIPEMD160 {
constructor() {
this.state = new Uint32Array(5);
this.msg = new Uint32Array(16);
this.block = Buffer.alloc(64);
this.size = FINALIZED;
}
init() {
this.state[0] = 0x67452301;
this.state[1] = 0xefcdab89;
this.state[2] = 0x98badcfe;
this.state[3] = 0x10325476;
this.state[4] = 0xc3d2e1f0;
this.size = 0;
return this;
}
update(data) {
assert(Buffer.isBuffer(data));
this._update(data, data.length);
return this;
}
final() {
return this._final(Buffer.alloc(20));
}
_update(data, len) {
assert(this.size !== FINALIZED, 'Context is not initialized.');
let pos = this.size & 63;
let off = 0;
this.size += len;
if (pos > 0) {
let want = 64 - pos;
if (want > len)
want = len;
data.copy(this.block, pos, off, off + want);
pos += want;
len -= want;
off += want;
if (pos < 64)
return;
this._transform(this.block, 0);
}
while (len >= 64) {
this._transform(data, off);
off += 64;
len -= 64;
}
if (len > 0)
data.copy(this.block, 0, off, off + len);
}
_final(out) {
assert(this.size !== FINALIZED, 'Context is not initialized.');
const pos = this.size & 63;
const len = this.size * 8;
writeU32(DESC, len >>> 0, 0);
writeU32(DESC, (len * (1 / 0x100000000)) >>> 0, 4);
this._update(PADDING, 1 + ((119 - pos) & 63));
this._update(DESC, 8);
for (let i = 0; i < 5; i++) {
writeU32(out, this.state[i], i * 4);
this.state[i] = 0;
}
for (let i = 0; i < 16; i++)
this.msg[i] = 0;
for (let i = 0; i < 64; i++)
this.block[i] = 0;
this.size = FINALIZED;
return out;
}
_transform(chunk, pos) {
const W = this.msg;
let A = this.state[0];
let B = this.state[1];
let C = this.state[2];
let D = this.state[3];
let E = this.state[4];
let Ah = A;
let Bh = B;
let Ch = C;
let Dh = D;
let Eh = E;
for (let i = 0; i < 16; i++)
W[i] = readU32(chunk, pos + i * 4);
for (let j = 0; j < 80; j++) {
let a = A + f(j, B, C, D) + W[r[j]] + K(j);
let b = rotl32(a, s[j]);
let T = b + E;
A = E;
E = D;
D = rotl32(C, 10);
C = B;
B = T;
a = Ah + f(79 - j, Bh, Ch, Dh) + W[rh[j]] + Kh(j);
b = rotl32(a, sh[j]);
T = b + Eh;
Ah = Eh;
Eh = Dh;
Dh = rotl32(Ch, 10);
Ch = Bh;
Bh = T;
}
const T = this.state[1] + C + Dh;
this.state[1] = this.state[2] + D + Eh;
this.state[2] = this.state[3] + E + Ah;
this.state[3] = this.state[4] + A + Bh;
this.state[4] = this.state[0] + B + Ch;
this.state[0] = T;
}
static hash() {
return new RIPEMD160();
}
static hmac() {
return new HMAC(RIPEMD160, 64);
}
static digest(data) {
return RIPEMD160.ctx.init().update(data).final();
}
static root(left, right) {
assert(Buffer.isBuffer(left) && left.length === 20);
assert(Buffer.isBuffer(right) && right.length === 20);
return RIPEMD160.ctx.init().update(left).update(right).final();
}
static multi(x, y, z) {
const {ctx} = RIPEMD160;
ctx.init();
ctx.update(x);
ctx.update(y);
if (z)
ctx.update(z);
return ctx.final();
}
static mac(data, key) {
return RIPEMD160.hmac().init(key).update(data).final();
}
}
/*
* Static
*/
RIPEMD160.native = 0;
RIPEMD160.id = 'RIPEMD160';
RIPEMD160.size = 20;
RIPEMD160.bits = 160;
RIPEMD160.blockSize = 64;
RIPEMD160.zero = Buffer.alloc(20, 0x00);
RIPEMD160.ctx = new RIPEMD160();
/*
* Helpers
*/
function rotl32(w, b) {
return (w << b) | (w >>> (32 - b));
}
function f(j, x, y, z) {
if (j <= 15)
return x ^ y ^ z;
if (j <= 31)
return (x & y) | ((~x) & z);
if (j <= 47)
return (x | (~y)) ^ z;
if (j <= 63)
return (x & z) | (y & (~z));
return x ^ (y | (~z));
}
function K(j) {
if (j <= 15)
return 0x00000000;
if (j <= 31)
return 0x5a827999;
if (j <= 47)
return 0x6ed9eba1;
if (j <= 63)
return 0x8f1bbcdc;
return 0xa953fd4e;
}
function Kh(j) {
if (j <= 15)
return 0x50a28be6;
if (j <= 31)
return 0x5c4dd124;
if (j <= 47)
return 0x6d703ef3;
if (j <= 63)
return 0x7a6d76e9;
return 0x00000000;
}
function readU32(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off] * 0x1000000);
}
function writeU32(dst, num, off) {
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
return off;
}
/*
* Expose
*/
module.exports = RIPEMD160;
}],
[/* 22 */ 'bcrypto', '/lib/hash256-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* hash256.js - hash256 for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(23 /* './js/hash256' */);
}],
[/* 23 */ 'bcrypto', '/lib/js/hash256.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* hash256.js - Hash256 implementation for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Resources:
* https://github.com/bitcoin/bitcoin/blob/master/src/hash.h
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const SHA256 = __node_require__(20 /* './sha256' */);
const HMAC = __node_require__(17 /* '../internal/hmac' */);
/**
* Hash256
*/
class Hash256 {
constructor() {
this.ctx = new SHA256();
}
init() {
this.ctx.init();
return this;
}
update(data) {
this.ctx.update(data);
return this;
}
final() {
const out = Buffer.alloc(32);
this.ctx._final(out);
this.ctx.init();
this.ctx.update(out);
this.ctx._final(out);
return out;
}
static hash() {
return new Hash256();
}
static hmac() {
return new HMAC(Hash256, 64);
}
static digest(data) {
return Hash256.ctx.init().update(data).final();
}
static root(left, right) {
assert(Buffer.isBuffer(left) && left.length === 32);
assert(Buffer.isBuffer(right) && right.length === 32);
return Hash256.ctx.init().update(left).update(right).final();
}
static multi(x, y, z) {
const {ctx} = Hash256;
ctx.init();
ctx.update(x);
ctx.update(y);
if (z)
ctx.update(z);
return ctx.final();
}
static mac(data, key) {
return Hash256.hmac().init(key).update(data).final();
}
}
/*
* Static
*/
Hash256.native = 0;
Hash256.id = 'HASH256';
Hash256.size = 32;
Hash256.bits = 256;
Hash256.blockSize = 64;
Hash256.zero = Buffer.alloc(32, 0x00);
Hash256.ctx = new Hash256();
/*
* Expose
*/
module.exports = Hash256;
}],
[/* 24 */ 'bcrypto', '/lib/cleanse-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* cleanse.js - cleanse for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(25 /* './js/cleanse' */);
}],
[/* 25 */ 'bcrypto', '/lib/js/cleanse.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* cleanse.js - memzero for bcrypto
* Copyright (c) 2016-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const random = __node_require__(26 /* '../random' */);
/**
* A maybe-secure memzero.
* @param {Buffer} data
*/
function cleanse(data) {
assert(Buffer.isBuffer(data));
random.randomFill(data, 0, data.length);
}
/*
* Static
*/
cleanse.native = 0;
/*
* Expose
*/
module.exports = cleanse;
}],
[/* 26 */ 'bcrypto', '/lib/random-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* random.js - random for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(27 /* './js/random' */);
}],
[/* 27 */ 'bcrypto', '/lib/js/random.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* random.js - random number generator for bcrypto
* Copyright (c) 2014-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Resources:
* https://wiki.openssl.org/index.php/Random_Numbers
* https://csrc.nist.gov/projects/random-bit-generation/
* http://www.pcg-random.org/posts/bounded-rands.html
* https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
/*
* Constants
*/
const crypto = global.crypto || global.msCrypto;
const HAS_CRYPTO = crypto && typeof crypto.getRandomValues === 'function';
const randomValues = HAS_CRYPTO ? crypto.getRandomValues.bind(crypto) : null;
const pool = new Uint32Array(16);
const MAX_BYTES = 65536;
let poolPos = 0;
/**
* Generate pseudo-random bytes.
* @param {Number} size
* @returns {Buffer}
*/
function randomBytes(size) {
assert((size >>> 0) === size);
const data = Buffer.alloc(size);
randomFillSync(data, 0, size);
return data;
}
/**
* Generate pseudo-random bytes.
* @param {Buffer} data
* @param {Number} [off=0]
* @param {Number} [size=data.length-off]
* @returns {Buffer}
*/
function randomFill(data, off, size) {
assert(Buffer.isBuffer(data));
if (off == null)
off = 0;
assert((off >>> 0) === off);
if (size == null)
size = data.length - off;
assert((size >>> 0) === size);
assert(off + size <= data.length);
randomFillSync(data, off, size);
return data;
}
/**
* Generate a random uint32.
* @returns {Number}
*/
function randomInt() {
if ((poolPos & 15) === 0) {
getRandomValues(pool);
poolPos = 0;
}
return pool[poolPos++];
}
/**
* Generate a random uint32 within a range.
* @param {Number} min - Inclusive.
* @param {Number} max - Exclusive.
* @returns {Number}
*/
function randomRange(min, max) {
assert((min >>> 0) === min);
assert((max >>> 0) === max);
assert(max >= min);
const space = max - min;
if (space === 0)
return min;
const top = -space >>> 0;
let x, r;
do {
x = randomInt();
r = x % space;
} while (x - r > top);
return r + min;
}
/*
* Helpers
*/
function getRandomValues(array) {
if (!HAS_CRYPTO)
throw new Error('Entropy source not available.');
return randomValues(array);
}
function randomFillSync(data, off, size) {
assert(Buffer.isBuffer(data));
assert(data.buffer instanceof ArrayBuffer);
assert((data.byteOffset >>> 0) === data.byteOffset);
assert((data.byteLength >>> 0) === data.byteLength);
assert((off >>> 0) === off);
assert((size >>> 0) === size);
assert(off + size <= data.byteLength);
if (size > 2 ** 31 - 1)
throw new RangeError('The value "size" is out of range.');
const offset = data.byteOffset + off;
const array = new Uint8Array(data.buffer, offset, size);
if (array.length > MAX_BYTES) {
for (let i = 0; i < array.length; i += MAX_BYTES) {
let j = i + MAX_BYTES;
if (j > array.length)
j = array.length;
getRandomValues(array.subarray(i, j));
}
} else {
if (array.length > 0)
getRandomValues(array);
}
}
/*
* Expose
*/
exports.native = 0;
exports.randomBytes = randomBytes;
exports.randomFill = randomFill;
exports.randomInt = randomInt;
exports.randomRange = randomRange;
}],
[/* 28 */ 'bcrypto', '/lib/secp256k1-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* secp256k1.js - secp256k1 for bcrypto
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(29 /* './js/secp256k1' */);
}],
[/* 29 */ 'bcrypto', '/lib/js/secp256k1.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* secp256k1.js - secp256k1 for bcrypto
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
const ECDSA = __node_require__(30 /* './ecdsa' */);
const SHA256 = __node_require__(39 /* '../sha256' */);
const pre = __node_require__(43 /* './precomputed/secp256k1.json' */);
/*
* Expose
*/
module.exports = new ECDSA('SECP256K1', SHA256, SHA256, pre);
}],
[/* 30 */ 'bcrypto', '/lib/js/ecdsa.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* ecdsa.js - ECDSA for bcrypto
* Copyright (c) 2018-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on indutny/elliptic:
* Copyright (c) 2014, Fedor Indutny (MIT License).
* https://github.com/indutny/elliptic
*
* References:
*
* [SEC1] SEC 1: Elliptic Curve Cryptography, Version 2.0
* Certicom Research
* http://www.secg.org/sec1-v2.pdf
*
* [FIPS186] Suite B Implementer's Guide to FIPS 186-3 (ECDSA)
* https://tinyurl.com/fips186-guide
*
* [GECC] Guide to Elliptic Curve Cryptography
* D. Hankerson, A. Menezes, and S. Vanstone
* https://tinyurl.com/guide-to-ecc
*
* [RFC6979] Deterministic Usage of the Digital Signature
* Algorithm (DSA) and Elliptic Curve Digital
* Signature Algorithm (ECDSA)
* T. Pornin
* https://tools.ietf.org/html/rfc6979
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const BN = __node_require__(31 /* '../bn' */);
const rng = __node_require__(26 /* '../random' */);
const asn1 = __node_require__(34 /* '../internal/asn1' */);
const Schnorr = __node_require__(35 /* './schnorr-legacy' */);
const HmacDRBG = __node_require__(40 /* '../hmac-drbg' */);
const elliptic = __node_require__(42 /* './elliptic' */);
/**
* ECDSA
*/
class ECDSA {
constructor(name, hash, xof, pre) {
assert(typeof name === 'string');
assert(hash);
assert(xof);
this.id = name;
this.type = 'ecdsa';
this.hash = hash;
this.xof = xof;
this.native = 0;
this._pre = pre || null;
this._curve = null;
this._schnorr = null;
}
get curve() {
if (!this._curve) {
this._curve = elliptic.curve(this.id, this._pre);
this._curve.precompute(rng);
this._pre = null;
}
return this._curve;
}
get schnorr() {
if (!this._schnorr)
this._schnorr = new Schnorr(this.curve, this.xof);
return this._schnorr;
}
get size() {
return this.curve.fieldSize;
}
get bits() {
return this.curve.fieldBits;
}
privateKeyGenerate() {
const a = this.curve.randomScalar(rng);
return this.curve.encodeScalar(a);
}
privateKeyVerify(key) {
assert(Buffer.isBuffer(key));
let a;
try {
a = this.curve.decodeScalar(key);
} catch (e) {
return false;
}
return !a.isZero() && a.cmp(this.curve.n) < 0;
}
privateKeyExport(key) {
const pub = this.publicKeyCreate(key, false);
const {x, y} = this.publicKeyExport(pub);
return {
d: Buffer.from(key),
x,
y
};
}
privateKeyImport(json) {
assert(json && typeof json === 'object');
const a = BN.decode(json.d, this.curve.endian);
if (a.isZero() || a.cmp(this.curve.n) >= 0)
throw new Error('Invalid private key.');
return this.curve.encodeScalar(a);
}
privateKeyTweakAdd(key, tweak) {
const t = this.curve.decodeScalar(tweak);
if (t.cmp(this.curve.n) >= 0)
throw new Error('Invalid scalar.');
const a = this.curve.decodeScalar(key);
if (a.isZero() || a.cmp(this.curve.n) >= 0)
throw new Error('Invalid private key.');
const k = a.add(t).imod(this.curve.n);
if (k.isZero())
throw new Error('Invalid private key.');
return this.curve.encodeScalar(k);
}
privateKeyTweakMul(key, tweak) {
const t = this.curve.decodeScalar(tweak);
if (t.isZero() || t.cmp(this.curve.n) >= 0)
throw new Error('Invalid scalar.');
const a = this.curve.decodeScalar(key);
if (a.isZero() || a.cmp(this.curve.n) >= 0)
throw new Error('Invalid private key.');
const k = a.mul(t).imod(this.curve.n);
if (k.isZero())
throw new Error('Invalid private key.');
return this.curve.encodeScalar(k);
}
privateKeyNegate(key) {
const a = this.curve.decodeScalar(key);
if (a.isZero() || a.cmp(this.curve.n) >= 0)
throw new Error('Invalid private key.');
const k = a.neg().imod(this.curve.n);
return this.curve.encodeScalar(k);
}
privateKeyInvert(key) {
const a = this.curve.decodeScalar(key);
if (a.isZero() || a.cmp(this.curve.n) >= 0)
throw new Error('Invalid private key.');
const k = a.invert(this.curve.n);
return this.curve.encodeScalar(k);
}
publicKeyCreate(key, compress) {
const a = this.curve.decodeScalar(key);
if (a.isZero() || a.cmp(this.curve.n) >= 0)
throw new Error('Invalid private key.');
const A = this.curve.g.mulBlind(a);
return A.encode(compress);
}
publicKeyConvert(key, compress) {
const A = this.curve.decodePoint(key);
return A.encode(compress);
}
publicKeyFromUniform(bytes, compress) {
const u = this.curve.decodeUniform(bytes);
const A = this.curve.pointFromUniform(u);
return A.encode(compress);
}
publicKeyToUniform(key, hint = rng.randomInt()) {
const A = this.curve.decodePoint(key);
const u = this.curve.pointToUniform(A, hint);
return this.curve.encodeUniform(u, hint >>> 8);
}
publicKeyFromHash(bytes, compress) {
const A = this.curve.pointFromHash(bytes);
return A.encode(compress);
}
publicKeyToHash(key) {
const A = this.curve.decodePoint(key);
return this.curve.pointToHash(A, 0, rng);
}
publicKeyVerify(key) {
assert(Buffer.isBuffer(key));
try {
this.curve.decodePoint(key);
} catch (e) {
return false;
}
return true;
}
publicKeyExport(key) {
const {x, y} = this.curve.decodePoint(key);
return {
x: this.curve.encodeField(x.fromRed()),
y: this.curve.encodeField(y.fromRed())
};
}
publicKeyImport(json, compress) {
assert(json && typeof json === 'object');
const x = BN.decode(json.x, this.curve.endian);
if (x.cmp(this.curve.p) >= 0)
throw new Error('Invalid point.');
if (json.y != null) {
const y = BN.decode(json.y, this.curve.endian);
if (y.cmp(this.curve.p) >= 0)
throw new Error('Invalid point.');
const A = this.curve.point(x, y);
if (!A.validate())
throw new Error('Invalid point.');
return A.encode(compress);
}
const A = this.curve.pointFromX(x, json.sign);
return A.encode(compress);
}
publicKeyTweakAdd(key, tweak, compress) {
const t = this.curve.decodeScalar(tweak);
if (t.cmp(this.curve.n) >= 0)
throw new Error('Invalid scalar.');
const A = this.curve.decodePoint(key);
const T = this.curve.g.jmul(t);
const P = T.add(A);
return P.encode(compress);
}
publicKeyTweakMul(key, tweak, compress) {
const t = this.curve.decodeScalar(tweak);
if (t.isZero() || t.cmp(this.curve.n) >= 0)
throw new Error('Invalid scalar.');
const A = this.curve.decodePoint(key);
const P = A.mul(t);
return P.encode(compress);
}
publicKeyCombine(keys, compress) {
assert(Array.isArray(keys));
let P = this.curve.jpoint();
for (const key of keys) {
const A = this.curve.decodePoint(key);
P = P.add(A);
}
return P.encode(compress);
}
publicKeyNegate(key, compress) {
const A = this.curve.decodePoint(key);
const P = A.neg();
return P.encode(compress);
}
signatureNormalize(sig) {
const [r, s] = this._decodeCompact(sig);
if (s.cmp(this.curve.nh) > 0)
s.ineg().imod(this.curve.n);
return this._encodeCompact(r, s);
}
signatureNormalizeDER(sig) {
const [r, s] = this._decodeDER(sig, false);
if (s.cmp(this.curve.nh) > 0)
s.ineg().imod(this.curve.n);
return this._encodeDER(r, s);
}
signatureExport(sig) {
const [r, s] = this._decodeCompact(sig);
return this._encodeDER(r, s);
}
signatureImport(sig) {
const [r, s] = this._decodeDER(sig, false);
return this._encodeCompact(r, s);
}
isLowS(sig) {
assert(Buffer.isBuffer(sig));
let s;
try {
[, s] = this._decodeCompact(sig);
} catch (e) {
return false;
}
return s.cmp(this.curve.nh) <= 0;
}
isLowDER(sig) {
assert(Buffer.isBuffer(sig));
let s;
try {
[, s] = this._decodeDER(sig, false);
} catch (e) {
return false;
}
return s.cmp(this.curve.nh) <= 0;
}
sign(msg, key) {
const [r, s] = this._sign(msg, key);
return this._encodeCompact(r, s);
}
signRecoverable(msg, key) {
const [r, s, param] = this._sign(msg, key);
return [this._encodeCompact(r, s), param];
}
signDER(msg, key) {
const [r, s] = this._sign(msg, key);
return this._encodeDER(r, s);
}
signRecoverableDER(msg, key) {
const [r, s, param] = this._sign(msg, key);
return [this._encodeDER(r, s), param];
}
_sign(msg, key) {
// ECDSA Signing.
//
// [SEC1] Page 44, Section 4.1.3.
// [GECC] Algorithm 4.29, Page 184, Section 4.4.1.
// [RFC6979] Page 9, Section 2.4.
// [RFC6979] Page 10, Section 3.2.
//
// Assumptions:
//
// - Let `m` be an integer reduced from bytes.
// - Let `a` be a secret non-zero scalar.
// - Let `k` be a random non-zero scalar.
// - R != O, r != 0, s != 0.
//
// Computation:
//
// k = random integer in [1,n-1]
// R = G * k
// r = x(R) mod n
// s = (r * a + m) / k mod n
// s = -s mod n, if s > n / 2
// S = (r, s)
//
// We can blind the scalar arithmetic
// with a random integer `b` like so:
//
// b = random integer in [1,n-1]
// s = (r * (a * b) + m * b) / (k * b) mod n
//
// Note that `k` must remain secret,
// otherwise an attacker can compute:
//
// a = (s * k - m) / r mod n
//
// This means that if two signatures
// share the same `r` value, an attacker
// can compute:
//
// k = (m1 - m2) / (+-s1 - +-s2) mod n
// a = (s1 * k - m1) / r mod n
//
// Assuming:
//
// s1 = (r * a + m1) / k mod n
// s2 = (r * a + m2) / k mod n
//
// To mitigate this, `k` can be generated
// deterministically using the HMAC-DRBG
// construction described in [RFC6979].
const {n, nh} = this.curve;
const G = this.curve.g;
const a = this.curve.decodeScalar(key);
if (a.isZero() || a.cmp(n) >= 0)
throw new Error('Invalid private key.');
const m = this._reduce(msg);
const nonce = this.curve.encodeScalar(m);
const drbg = new HmacDRBG(this.hash, key, nonce);
for (;;) {
const bytes = drbg.generate(this.curve.scalarSize);
const k = this._truncate(bytes);
if (k.isZero() || k.cmp(n) >= 0)
continue;
const R = G.mulBlind(k);
if (R.isInfinity())
continue;
const x = R.getX();
const r = x.mod(n);
if (r.isZero())
continue;
const b = this.curve.randomScalar(rng);
const ki = k.mul(b).fermat(n);
const ba = a.mul(b).imod(n);
const bm = m.mul(b).imod(n);
const sk = r.mul(ba).iadd(bm).imod(n);
const s = sk.mul(ki).imod(n);
if (s.isZero())
continue;
let param = R.isOdd() | (!x.eq(r) << 1);
if (s.cmp(nh) > 0) {
s.ineg().imod(n);
param ^= 1;
}
return [r, s, param];
}
}
verify(msg, sig, key) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
let r, s;
try {
[r, s] = this._decodeCompact(sig);
} catch (e) {
return false;
}
try {
return this._verify(msg, r, s, key);
} catch (e) {
return false;
}
}
verifyDER(msg, sig, key) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
let r, s;
try {
[r, s] = this._decodeDER(sig, false);
} catch (e) {
return false;
}
try {
return this._verify(msg, r, s, key);
} catch (e) {
return false;
}
}
_verify(msg, r, s, key) {
// ECDSA Verification.
//
// [SEC1] Page 46, Section 4.1.4.
// [GECC] Algorithm 4.30, Page 184, Section 4.4.1.
//
// Assumptions:
//
// - Let `m` be an integer reduced from bytes.
// - Let `r` and `s` be signature elements.
// - Let `A` be a valid group element.
// - r != 0, r < n.
// - s != 0, s < n.
// - R != O.
//
// Computation:
//
// u1 = m / s mod n
// u2 = r / s mod n
// R = G * u1 + A * u2
// r == x(R) mod n
//
// Note that the signer can verify their
// own signatures more efficiently with:
//
// R = G * ((u1 + u2 * a) mod n)
//
// Furthermore, we can avoid affinization
// of `R` by scaling `r` by `z^2` and
// repeatedly adding `n * z^2` to it up
// to a certain threshold.
const {n} = this.curve;
const G = this.curve.g;
const m = this._reduce(msg);
const A = this.curve.decodePoint(key);
if (r.isZero() || r.cmp(n) >= 0)
return false;
if (s.isZero() || s.cmp(n) >= 0)
return false;
const si = s.invert(n);
const u1 = m.mul(si).imod(n);
const u2 = r.mul(si).imod(n);
const R = G.jmulAdd(u1, A, u2);
return R.eqR(r);
}
recover(msg, sig, param, compress) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert((param >>> 0) === param);
assert((param & 3) === param, 'The recovery param is more than two bits.');
let r, s;
try {
[r, s] = this._decodeCompact(sig);
} catch (e) {
return null;
}
let A;
try {
A = this._recover(msg, r, s, param);
} catch (e) {
return null;
}
return A.encode(compress);
}
recoverDER(msg, sig, param, compress) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert((param >>> 0) === param);
assert((param & 3) === param, 'The recovery param is more than two bits.');
let r, s;
try {
[r, s] = this._decodeDER(sig, false);
} catch (e) {
return null;
}
let A;
try {
A = this._recover(msg, r, s, param);
} catch (e) {
return null;
}
return A.encode(compress);
}
_recover(msg, r, s, param) {
// ECDSA Public Key Recovery.
//
// [SEC1] Page 47, Section 4.1.6.
//
// Assumptions:
//
// - Let `m` be an integer reduced from bytes.
// - Let `r` and `s` be signature elements.
// - Let `i` be an integer in [0,3].
// - x^3 + a * x + b is square in F(p).
// - If i > 1 then r < (p mod n).
// - r != 0, r < n.
// - s != 0, s < n.
// - A != O.
//
// Computation:
//
// x = r + n, if i > 1
// = r, otherwise
// R' = (x, sqrt(x^3 + a * x + b))
// R = -R', if i mod 2 == 1
// = +R', otherwise
// s1 = m / r mod n
// s2 = s / r mod n
// A = R * s2 - G * s1
//
// Note that this implementation will have
// trouble on curves where `p / n > 1`.
const {n, pmodn} = this.curve;
const G = this.curve.g;
const m = this._reduce(msg);
if (r.isZero() || r.cmp(n) >= 0)
throw new Error('Invalid R value.');
if (s.isZero() || s.cmp(n) >= 0)
throw new Error('Invalid S value.');
const sign = (param & 1) !== 0;
const high = param >>> 1;
let x = r;
if (high) {
if (this.curve.highOrder)
throw new Error('Invalid high bit.');
if (x.cmp(pmodn) >= 0)
throw new Error('Invalid R value.');
x = x.add(n);
}
const R = this.curve.pointFromX(x, sign);
const ri = r.invert(n);
const s1 = m.mul(ri).ineg().imod(n);
const s2 = s.mul(ri).imod(n);
const A = G.mulAdd(s1, R, s2);
if (A.isInfinity())
throw new Error('Invalid point.');
return A;
}
derive(pub, priv, compress) {
const A = this.curve.decodePoint(pub);
const a = this.curve.decodeScalar(priv);
if (a.isZero() || a.cmp(this.curve.n) >= 0)
throw new Error('Invalid private key.');
if (this.curve.h.cmpn(1) > 0) {
if (A.isSmall())
throw new Error('Invalid point.');
}
const P = A.mulBlind(a, rng);
return P.encode(compress);
}
/*
* Schnorr
*/
schnorrSign(msg, key) {
return this.schnorr.sign(msg, key);
}
schnorrVerify(msg, sig, key) {
return this.schnorr.verify(msg, sig, key);
}
schnorrVerifyBatch(batch) {
return this.schnorr.verifyBatch(batch);
}
/*
* Helpers
*/
_encodeCompact(r, s) {
return Buffer.concat([
this.curve.encodeScalar(r),
this.curve.encodeScalar(s)
]);
}
_decodeCompact(sig) {
assert(Buffer.isBuffer(sig));
const {n} = this.curve;
const size = this.curve.scalarSize;
if (sig.length !== size * 2)
throw new Error('Invalid signature size.');
const Rraw = sig.slice(0, size);
const Sraw = sig.slice(size, size * 2);
const r = this.curve.decodeScalar(Rraw);
const s = this.curve.decodeScalar(Sraw);
if (r.cmp(n) >= 0 || s.cmp(n) >= 0)
throw new Error('Invalid signature.');
return [r, s];
}
_encodeDER(r, s) {
const size = asn1.sizeInt(r) + asn1.sizeInt(s);
const out = Buffer.alloc(asn1.sizeSeq(size));
let pos = 0;
pos = asn1.writeSeq(out, pos, size);
pos = asn1.writeInt(out, pos, r);
pos = asn1.writeInt(out, pos, s);
assert(pos === out.length);
return out;
}
_decodeDER(sig, strict) {
assert(Buffer.isBuffer(sig));
assert(typeof strict === 'boolean');
const {n} = this.curve;
let pos = 0;
let r, s;
pos = asn1.readSeq(sig, pos, strict);
[r, pos] = asn1.readInt(sig, pos, strict);
[s, pos] = asn1.readInt(sig, pos, strict);
if (strict && pos !== sig.length)
throw new Error('Trailing bytes.');
if (r.cmp(n) >= 0 || s.cmp(n) >= 0)
throw new Error('Invalid signature.');
return [r, s];
}
_truncate(msg) {
// Byte array to integer conversion.
//
// [SEC1] Step 5, Page 45, Section 4.1.3.
// [FIPS186] Page 25, Section B.2.
//
// The two sources above disagree on this.
//
// FIPS186 simply modulos the entire byte
// array by the order, whereas SEC1 takes
// the left-most ceil(log2(n+1)) bits modulo
// the order (and maybe does other stuff).
//
// Instead of trying to decipher all of
// this nonsense, we simply replicate the
// OpenSSL behavior (which, in actuality,
// is more similar to the SEC1 behavior).
assert(Buffer.isBuffer(msg));
const bits = this.curve.n.bitLength();
const bytes = (bits + 7) >>> 3;
if (msg.length > bytes)
msg = msg.slice(0, bytes);
const m = BN.decode(msg, this.curve.endian);
const d = msg.length * 8 - bits;
if (d > 0)
m.iushrn(d);
return m;
}
_reduce(msg) {
return this._truncate(msg).imod(this.curve.n);
}
}
/*
* Expose
*/
module.exports = ECDSA;
}],
[/* 31 */ 'bcrypto', '/lib/bn-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* bn.js - big numbers for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(32 /* './js/bn' */);
}],
[/* 32 */ 'bcrypto', '/lib/js/bn.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* bn.js - big numbers for bcrypto
* Copyright (c) 2018-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on indutny/bn.js:
* Copyright (c) 2015, Fedor Indutny (MIT License).
* https://github.com/indutny/bn.js
*
* Parts of this software are based on golang/go:
* Copyright (c) 2009, The Go Authors. All rights reserved.
* https://github.com/golang/go
*
* Parts of this software are based on openssl/openssl:
* Copyright (c) 1998-2018, The OpenSSL Project (Apache License v2.0).
* Copyright (c) 1995-1998, Eric A. Young, Tim J. Hudson. All rights reserved.
* https://github.com/openssl/openssl
*
* Parts of this software are based on libgmp:
* Copyright (c) 1991-1997, 1999-2014, Free Software Foundation, Inc.
* https://gmplib.org/
*
* Parts of this software are based on v8/v8:
* Copyright (c) 2017, The V8 Project Authors (BSD-Style License).
* https://github.com/v8/v8
*
* Resources:
* https://github.com/indutny/bn.js/blob/master/lib/bn.js
* https://github.com/indutny/miller-rabin/blob/master/lib/mr.js
* https://github.com/golang/go/blob/master/src/math/big/int.go
* https://github.com/golang/go/blob/master/src/math/big/nat.go
* https://github.com/golang/go/blob/master/src/math/big/prime.go
* https://github.com/openssl/openssl/tree/master/crypto/bn
* https://github.com/openssl/openssl/blob/master/crypto/bn/bn_kron.c
* https://github.com/gnutls/nettle/blob/master/mini-gmp.c
* https://github.com/v8/v8/blob/master/src/objects/bigint.cc
*/
/* eslint valid-typeof: "off" */
'use strict';
const {custom} = __node_require__(33 /* '../internal/custom' */);
/*
* Constants
*/
const zeros = [
'',
'0',
'00',
'000',
'0000',
'00000',
'000000',
'0000000',
'00000000',
'000000000',
'0000000000',
'00000000000',
'000000000000',
'0000000000000',
'00000000000000',
'000000000000000',
'0000000000000000',
'00000000000000000',
'000000000000000000',
'0000000000000000000',
'00000000000000000000',
'000000000000000000000',
'0000000000000000000000',
'00000000000000000000000',
'000000000000000000000000',
'0000000000000000000000000'
];
const groupSizes = [
0x00, 0x19, 0x10, 0x0c, 0x0b, 0x0a,
0x09, 0x08, 0x08, 0x07, 0x07, 0x07,
0x07, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05
];
const groupBases = [
0x00000000, 0x02000000, 0x0290d741, 0x01000000,
0x02e90edd, 0x039aa400, 0x0267bf47, 0x01000000,
0x0290d741, 0x00989680, 0x012959c3, 0x0222c000,
0x03bd7765, 0x0072e440, 0x00adcea1, 0x01000000,
0x01704f61, 0x0206fc40, 0x02cddcf9, 0x03d09000,
0x003e5185, 0x004ea360, 0x006235f7, 0x00798000,
0x009502f9, 0x00b54ba0, 0x00daf26b, 0x01069c00,
0x0138f9ad, 0x0172c9e0, 0x01b4d89f, 0x02000000,
0x025528a1, 0x02b54a20, 0x03216b93, 0x039aa400
];
const primes = {
p192: null,
p224: null,
p521: null,
k256: null,
p251: null,
p25519: null,
p448: null
};
const modes = {
NONE: 0,
QUO: 1,
REM: 2,
BOTH: 3,
EUCLID: 4,
ALL: 7
};
const WND_WIDTH = 4;
const WND_SIZE = 1 << (WND_WIDTH - 1);
const HAS_BIGINT = typeof BigInt === 'function';
/**
* BN
*/
class BN {
constructor(num, base, endian) {
this.words = [0];
this.length = 1;
this.negative = 0;
this.red = null;
this.from(num, base, endian);
}
/*
* Addition Engine
*/
_iadd(a, b) {
let carry = 0;
let i = 0;
// a.length > b.length
if (a.length < b.length)
[a, b] = [b, a];
if (a !== this)
this._alloc(a.length);
for (; i < b.length; i++) {
const r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
this.words[i] = r & 0x3ffffff;
carry = r >>> 26;
}
for (; carry !== 0 && i < a.length; i++) {
const r = (a.words[i] | 0) + carry;
this.words[i] = r & 0x3ffffff;
carry = r >>> 26;
}
this.length = a.length;
if (carry !== 0) {
this._alloc(this.length + 1);
this.words[this.length++] = carry;
} else if (a !== this) {
// Copy the rest of the words.
for (; i < a.length; i++)
this.words[i] = a.words[i];
}
// Note: we shouldn't need to strip here.
return this;
}
_iaddn(num) {
this.words[0] += num;
if (this.words[0] < 0x4000000)
return this;
// Carry.
let i = 0;
this._alloc(this.length + 1);
this.words[this.length] = 0;
for (; i < this.length && this.words[i] >= 0x4000000; i++) {
this.words[i] -= 0x4000000;
this.words[i + 1] += 1;
}
this.length = Math.max(this.length, i + 1);
// Note: we shouldn't need to strip here.
return this;
}
/*
* Addition
*/
iadd(num) {
enforce(BN.isBN(num), 'num', 'bignum');
if (this.negative === num.negative) {
// x + y == x + y
// (-x) + (-y) == -(x + y)
this._iadd(this, num);
} else {
// x + (-y) == x - y == -(y - x)
// (-x) + y == y - x == -(x - y)
const cmp = this.ucmp(num);
// x + (-x) == (-x) + x == 0
if (cmp === 0) {
this.words[0] = 0;
this.length = 1;
this.negative = 0;
return this;
}
if (cmp < 0) {
this._isub(num, this);
this.negative ^= 1;
} else {
this._isub(this, num);
}
}
return this;
}
iaddn(num) {
enforce(isSMI(num), 'num', 'smi');
const negative = (num < 0) | 0;
if (negative)
num = -num;
if (this.negative === negative) {
// x + y == x + y
// (-x) + (-y) == -(x + y)
this._iaddn(num);
} else {
// x + (-y) == x - y == -(y - x)
// (-x) + y == y - x == -(x - y)
if (this.length === 1 && this.words[0] < num) {
this.words[0] = num - this.words[0];
this.negative ^= 1;
} else {
this._isubn(num);
}
}
return this;
}
add(num) {
enforce(BN.isBN(num), 'num', 'bignum');
if (num.length > this.length)
return num.clone().iadd(this);
return this.clone().iadd(num);
}
addn(num) {
return this.clone().iaddn(num);
}
/*
* Subtraction Engine
*/
_isub(a, b) {
let carry = 0;
let i = 0;
// a > b
assert(a.length >= b.length);
if (a !== this)
this._alloc(a.length);
for (; i < b.length; i++) {
const r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
carry = r >> 26;
this.words[i] = r & 0x3ffffff;
}
for (; carry !== 0 && i < a.length; i++) {
const r = (a.words[i] | 0) + carry;
carry = r >> 26;
this.words[i] = r & 0x3ffffff;
}
assert(carry === 0);
// Copy rest of the words.
if (a !== this) {
for (; i < a.length; i++)
this.words[i] = a.words[i];
}
this.length = Math.max(this.length, i);
return this._strip();
}
_isubn(num) {
this.words[0] -= num;
if (this.words[0] >= 0)
return this._normalize();
assert(this.length !== 1);
// Carry.
this._alloc(this.length + 1);
for (let i = 0; i < this.length && this.words[i] < 0; i++) {
this.words[i] += 0x4000000;
this.words[i + 1] -= 1;
}
this.words[this.length] = 0;
return this._strip();
}
/*
* Subtraction
*/
isub(num) {
enforce(BN.isBN(num), 'num', 'bignum');
if (this.negative !== num.negative) {
// x - (-y) == x + y
// (-x) - y == -(x + y)
this._iadd(this, num);
} else {
// x - y == x - y == -(y - x)
// (-x) - (-y) == y - x == -(x - y)
const cmp = this.ucmp(num);
// x - x == 0
if (cmp === 0) {
this.words[0] = 0;
this.length = 1;
this.negative = 0;
return this;
}
if (cmp < 0) {
this._isub(num, this);
this.negative ^= 1;
} else {
this._isub(this, num);
}
}
return this;
}
isubn(num) {
enforce(isSMI(num), 'num', 'smi');
const negative = (num < 0) | 0;
if (negative)
num = -num;
if (this.negative !== negative) {
// x - (-y) == x + y
// (-x) - y == -(x + y)
this._iaddn(num);
} else {
// x - y == x - y == -(y - x)
// (-x) - (-y) == y - x == -(x - y)
if (this.length === 1 && this.words[0] < num) {
this.words[0] = num - this.words[0];
this.negative ^= 1;
} else {
this._isubn(num);
}
}
return this;
}
sub(num) {
return this.clone().isub(num);
}
subn(num) {
return this.clone().isubn(num);
}
/*
* Multiplication Engine
*/
_mul(num, out) {
enforce(BN.isBN(num), 'num', 'bignum');
enforce(BN.isBN(out), 'out', 'bignum');
if (this.length === 10 && num.length === 10)
return comb10MulTo(this, num, out);
const len = this.length + num.length;
if (len < 63)
return smallMulTo(this, num, out);
if (len < 1024)
return bigMulTo(this, num, out);
return jumboMulTo(this, num, out);
}
/*
* Multiplication
*/
imul(num) {
return this.mul(num)._move(this);
}
imuln(num) {
enforce(isSMI(num), 'num', 'smi');
const neg = (num < 0) | 0;
if (neg)
num = -num;
// Carry.
let carry = 0;
for (let i = 0; i < this.length; i++) {
const w = this.words[i] * num;
const lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
carry >>= 26;
carry += (w / 0x4000000) | 0;
carry += lo >>> 26;
this.words[i] = lo & 0x3ffffff;
}
this.negative ^= neg;
if (carry !== 0) {
this._alloc(this.length + 1);
this.words[this.length++] = carry;
} else {
this._strip();
}
return this;
}
mul(num) {
enforce(BN.isBN(num), 'num', 'bignum');
const len = this.length + num.length;
const out = new BN();
out.words = new Array(len);
for (let i = 0; i < len; i ++)
out.words[i] = 0;
return this._mul(num, out);
}
muln(num) {
return this.clone().imuln(num);
}
/*
* Multiplication + Shift
*/
mulShift(num, bits) {
enforce(BN.isBN(num), 'num', 'bignum');
enforce((bits >>> 0) === bits, 'bits', 'uint32');
const r = this.mul(num);
const b = r.utestn(bits - 1);
r.iushrn(bits);
if (this.negative ^ num.negative)
return r.isubn(b);
return r.iaddn(b);
}
/*
* Division Engine
*/
_div(num, flags) {
enforce(BN.isBN(num), 'num', 'bignum');
assert((flags & modes.ALL) === flags);
assert(flags !== modes.NONE);
const a = this;
const b = num;
nonzero(!b.isZero());
if (a.isZero())
return [new BN(0), new BN(0)];
const as = a.negative;
const bs = b.negative;
a.negative = 0;
b.negative = 0;
let q = null;
let r = null;
if (a.ucmp(b) < 0) {
if (flags & modes.QUO)
q = new BN(0);
if (flags & modes.REM)
r = a.clone();
} else if (b.length === 1) {
if (flags & modes.QUO)
q = a.quon(b.words[0]);
if (flags & modes.REM)
r = a.remn(b.words[0]);
} else {
[q, r] = a._wordDiv(b, flags);
}
a.negative = as;
b.negative = bs;
if (flags & modes.QUO) {
q.negative = a.negative ^ b.negative;
q._normalize();
}
if (flags & modes.REM) {
r.negative = a.negative;
r._normalize();
}
if (flags & modes.EUCLID) {
if (flags & modes.QUO) {
assert((flags & modes.REM) !== 0);
if (r.negative !== 0) {
if (b.negative !== 0)
q.iaddn(1);
else
q.isubn(1);
}
}
if (flags & modes.REM) {
if (r.negative !== 0) {
if (b.negative !== 0)
r.isub(b);
else
r.iadd(b);
}
}
}
return [q, r];
}
_wordDiv(num, flags) {
let a = this.clone();
let b = num;
let q = null;
let hi;
// Normalize.
const word = b.words[b.length - 1] | 0;
const shift = 26 - countBits(word);
if (shift !== 0) {
b = b.clone();
a.iushln(shift);
b.iushln(shift);
hi = b.words[b.length - 1] | 0;
} else {
hi = word;
}
// Initialize quotient.
const m = a.length - b.length;
assert(m >= 0);
if (flags & modes.QUO) {
q = new BN(0);
q.length = m + 1;
q.words = new Array(q.length);
for (let i = 0; i < q.length; i++)
q.words[i] = 0;
}
// Diff.
const d = a.clone();
d._ishlnsubmul(b, 1, m);
if (d.negative === 0) {
if (q)
q.words[m] = 1;
a = d;
}
// Divide.
for (let j = m - 1; j >= 0; j--) {
const ahi = a.words[b.length + j];
const alo = a.words[b.length + j - 1];
const quo = ((ahi * 0x4000000 + alo) / hi) | 0;
let qj = Math.min(quo, 0x3ffffff);
a._ishlnsubmul(b, qj, j);
while (a.negative !== 0) {
qj -= 1;
a.negative = 0;
a._ishlnsubmul(b, 1, j);
a.ineg();
}
if (q)
q.words[j] = qj;
}
// Strip.
if (q)
q._strip();
// Denormalize.
// Note: we shouldn't need to strip `a` here.
if ((flags & modes.REM) && shift !== 0)
a.iushrn(shift);
return [q, a];
}
_ishlnsubmul(num, mul, shift) {
let carry = 0;
let i = 0;
this._expand(num.length + shift);
for (; i < num.length; i++) {
const k = (this.words[i + shift] | 0) + carry;
const r = num.words[i] * mul;
const w = k - (r & 0x3ffffff);
carry = (w >> 26) - ((r / 0x4000000) | 0);
this.words[i + shift] = w & 0x3ffffff;
}
for (; i < this.length - shift; i++) {
const w = (this.words[i + shift] | 0) + carry;
carry = w >> 26;
this.words[i + shift] = w & 0x3ffffff;
}
if (carry === 0)
return this._strip();
// Subtraction overflow.
assert(carry === -1);
carry = 0;
for (let i = 0; i < this.length; i++) {
const w = -(this.words[i] | 0) + carry;
carry = w >> 26;
this.words[i] = w & 0x3ffffff;
}
this.negative = 1;
return this._strip();
}
/*
* Truncation Division + Modulo
*/
quorem(num) {
return this._div(num, modes.BOTH);
}
/*
* Truncation Division
*/
iquo(num) {
return this.quo(num)._move(this);
}
iquon(num) {
enforce(isSMI(num), 'num', 'smi');
nonzero(num !== 0);
const neg = (num < 0) | 0;
if (neg)
num = -num;
let carry = 0;
for (let i = this.length - 1; i >= 0; i--) {
const w = (this.words[i] | 0) + carry * 0x4000000;
this.words[i] = (w / num) | 0;
carry = w % num;
}
this.negative ^= neg;
return this._strip();
}
quo(num) {
return this._div(num, modes.QUO)[0];
}
quon(num) {
return this.clone().iquon(num);
}
/*
* Truncation Modulo
*/
irem(num) {
return this.rem(num)._move(this);
}
iremn(num) {
let m = this.remrn(num);
if (m < 0)
m = -m;
this.words[0] = m;
this.length = 1;
return this._normalize();
}
rem(num) {
return this._div(num, modes.REM)[1];
}
remn(num) {
return this.clone().iremn(num);
}
remrn(num) {
enforce(isSMI(num), 'num', 'smi');
nonzero(num !== 0);
if (num < 0)
num = -num;
const p = (1 << 26) % num;
let acc = 0;
for (let i = this.length - 1; i >= 0; i--)
acc = (p * acc + (this.words[i] | 0)) % num;
return this.negative !== 0 ? (-acc | 0) : acc;
}
/*
* Euclidean Division + Modulo
*/
divmod(num) {
return this._div(num, modes.BOTH | modes.EUCLID);
}
/*
* Euclidean Division
*/
idiv(num) {
return this.div(num)._move(this);
}
idivn(num) {
if (this.negative === 0)
return this.iquon(num);
const r = this.remrn(num);
this.iquon(num);
if (r < 0) {
if (num < 0)
this.iaddn(1);
else
this.isubn(1);
}
return this;
}
div(num) {
return this._div(num, modes.BOTH | modes.EUCLID)[0];
}
divn(num) {
return this.clone().idivn(num);
}
/*
* Euclidean Modulo
*/
imod(num) {
if (this.ucmp(num) < 0) {
if (this.negative !== 0) {
this._isub(num, this);
this.negative = 0;
}
return this;
}
return this.mod(num)._move(this);
}
imodn(num) {
this.words[0] = this.modrn(num);
this.length = 1;
this.negative = 0;
return this;
}
mod(num) {
return this._div(num, modes.REM | modes.EUCLID)[1];
}
modn(num) {
return this.clone().imodn(num);
}
modrn(num) {
enforce(isSMI(num), 'num', 'smi');
let r = this.remrn(num);
if (r < 0) {
if (num < 0)
r -= num;
else
r += num;
}
return r;
}
/*
* Round Division
*/
divRound(num) {
const [q, r] = this.quorem(num);
// Fast case - exact division.
if (r.isZero())
return q;
const bit = num.words[0] & 1;
num.iushrn(1);
const cmp = r.ucmp(num);
num.iushln(1);
num.words[0] |= bit;
// Round down.
if (cmp < 0 || (num.isOdd() && cmp === 0))
return q;
// Round up.
if (this.negative ^ num.negative)
return q.isubn(1);
return q.iaddn(1);
}
/*
* Exponentiation
*/
ipow(num) {
return this.pow(num)._move(this);
}
ipown(num) {
return this.pown(num)._move(this);
}
pow(num) {
enforce(BN.isBN(num), 'num', 'bignum');
let b = countBits(num.words[num.length - 1]);
let r = new BN(1);
for (let i = num.length - 1; i >= 0; i--) {
const word = num.words[i];
for (let j = b - 1; j >= 0; j--) {
r = r.sqr();
if ((word >> j) & 1)
r = r.mul(this);
}
b = 26;
}
return r;
}
pown(num) {
enforce(isSMI(num), 'num', 'smi');
if (num < 0)
num = -num;
if (num === 0)
return new BN(1);
if (num === 1)
return this.clone();
const bits = countBits(num);
let r = this;
for (let i = bits - 2; i >= 0; i--) {
r = r.sqr();
if ((num >> i) & 1)
r = r.mul(this);
}
return r;
}
isqr() {
return this.imul(this);
}
sqr() {
return this.mul(this);
}
/*
* Roots Engine
*/
_rootrem(pow, rem) {
enforce((pow >>> 0) === pow, 'num', 'uint32');
if (pow === 0)
throw new RangeError('Zeroth root.');
if (~pow & this.negative)
throw new RangeError('Negative with even root.');
if (this.ucmpn(1) <= 0)
return [this.clone(), new BN(0)];
let u = new BN(0);
let t = BN.shift(1, this.bitLength() / pow + 1 | 0);
let v, r;
if (this.negative !== 0)
t.ineg();
if (pow === 2) {
do {
u = t;
t = this.quo(u);
t.iadd(u);
t.iushrn(1);
} while (t.ucmp(u) < 0);
} else {
do {
u = t;
t = u.pown(pow - 1);
t = this.quo(t);
v = u.muln(pow - 1);
t.iadd(v);
t = t.quon(pow);
} while (t.ucmp(u) < 0);
}
if (rem) {
t = u.pown(pow);
r = this.sub(t);
}
return [u, r];
}
/*
* Roots
*/
rootrem(pow) {
return this._rootrem(pow, 1);
}
iroot(pow) {
return this.root(pow)._move(this);
}
root(pow) {
return this._rootrem(pow, 0)[0];
}
isPower(pow) {
enforce((pow >>> 0) === pow, 'num', 'uint32');
if (pow === 0 || (~pow & this.negative))
return false;
const [, r] = this.rootrem(pow);
return r.sign() === 0;
}
sqrtrem() {
return this.rootrem(2);
}
isqrt() {
return this.sqrt()._move(this);
}
sqrt() {
return this.root(2);
}
isSquare() {
return this.isPower(2);
}
/*
* AND
*/
iand(num) {
enforce(BN.isBN(num), 'num', 'bignum');
let x = this;
let y = num;
if (x === y)
return x;
if ((x.negative | y.negative) === 0)
return x.iuand(y);
if ((x.negative & y.negative) === 1) {
// (-x) & (-y) == ~(x-1) & ~(y-1)
// == ~((x-1) | (y-1))
// == -(((x-1) | (y-1)) + 1)
x.iaddn(1);
y.iaddn(1);
x.iuor(y);
x.isubn(1);
y.isubn(1);
return x;
}
// Assume x is the positive number.
if (x.negative !== 0)
[x, y] = [y.clone(), x];
// x & (-y) == x & ~(y-1)
// == x & ~(y-1)
const width = x.bitLength();
y.iaddn(1);
y.inotn(width);
x.iuand(y);
y.inotn(width);
y.isubn(1);
return x._move(this);
}
iandn(num) {
enforce(isSMI(num), 'num', 'smi');
if ((this.negative | (num < 0)) !== 0)
return this.iand(new BN(num));
this.words[0] &= num;
this.length = 1;
return this;
}
and(num) {
return this.clone().iand(num);
}
andn(num) {
return this.clone().iandn(num);
}
andrn(num) {
enforce(isSMI(num), 'num', 'smi');
if ((this.negative | (num < 0)) !== 0) {
const n = this.iand(new BN(num));
if (n.length > 1)
throw new RangeError('Number exceeds 26 bits.');
return n.negative !== 0 ? -n.words[0] : n.words[0];
}
return this.words[0] & num;
}
/*
* Unsigned AND
*/
iuand(num) {
enforce(BN.isBN(num), 'num', 'bignum');
this.length = Math.min(this.length, num.length);
for (let i = 0; i < this.length; i++)
this.words[i] &= num.words[i];
return this._strip();
}
iuandn(num) {
enforce(isSMI(num), 'num', 'smi');
this.words[0] &= Math.abs(num);
this.length = 1;
return this._normalize();
}
uand(num) {
return this.clone().iuand(num);
}
uandn(num) {
return this.clone().iuandn(num);
}
uandrn(num) {
enforce(isSMI(num), 'num', 'smi');
const n = this.words[0] & Math.abs(num);
return this.negative !== 0 ? (-n | 0) : n;
}
/*
* OR
*/
ior(num) {
enforce(BN.isBN(num), 'num', 'bignum');
let x = this;
let y = num;
if (x === y)
return x;
if ((x.negative | y.negative) === 0)
return x.iuor(y);
if ((x.negative & y.negative) === 1) {
// (-x) | (-y) == ~(x-1) | ~(y-1)
// == ~((x-1) & (y-1))
// == -(((x-1) & (y-1)) + 1)
x.iaddn(1);
y.iaddn(1);
x.iuand(y);
x.isubn(1);
y.isubn(1);
return x;
}
// Assume x is the positive number.
y = y.clone();
if (x.negative !== 0)
[x, y] = [y, x];
// x | (-y) == x | ~(y-1)
// == ~((y-1) & ~x)
// == -(((y-1) & ~x) + 1)
y.iaddn(1);
x.inotn(y.bitLength());
y.iuand(x);
y.isubn(1);
return y._move(this);
}
iorn(num) {
enforce(isSMI(num), 'num', 'smi');
if ((this.negative | (num < 0)) !== 0)
return this.ior(new BN(num));
this.words[0] |= num;
return this;
}
or(num) {
return this.clone().ior(num);
}
orn(num) {
return this.clone().iorn(num);
}
/*
* Unsigned OR
*/
iuor(num) {
enforce(BN.isBN(num), 'num', 'bignum');
this._expand(num.length);
for (let i = 0; i < num.length; i++)
this.words[i] |= num.words[i];
// Note: we shouldn't need to strip here.
return this;
}
iuorn(num) {
enforce(isSMI(num), 'num', 'smi');
this.words[0] |= Math.abs(num);
return this;
}
uor(num) {
return this.clone().iuor(num);
}
uorn(num) {
return this.clone().iuorn(num);
}
/*
* XOR
*/
ixor(num) {
enforce(BN.isBN(num), 'num', 'bignum');
let x = this;
let y = num;
if (x === y) {
x.words[0] = 0;
x.length = 1;
x.negative = 0;
return x;
}
if ((x.negative | y.negative) === 0)
return x.iuxor(y);
if ((x.negative & y.negative) === 1) {
// (-x) ^ (-y) == ~(x-1) ^ ~(y-1)
// == (x-1) ^ (y-1)
x.iaddn(1);
y.iaddn(1);
x.iuxor(y);
x.ineg();
y.isubn(1);
return x;
}
// Assume x is the positive number.
if (x.negative !== 0)
[x, y] = [y.clone(), x];
// x ^ (-y) == x ^ ~(y-1)
// == ~(x ^ (y-1))
// == -((x ^ (y-1)) + 1)
y.iaddn(1);
x.iuxor(y);
x.iaddn(1);
x.ineg();
y.isubn(1);
return x._move(this);
}
ixorn(num) {
enforce(isSMI(num), 'num', 'smi');
if ((this.negative | (num < 0)) !== 0)
return this.ixor(new BN(num));
this.words[0] ^= num;
return this;
}
xor(num) {
return this.clone().ixor(num);
}
xorn(num) {
return this.clone().ixorn(num);
}
/*
* Unsigned XOR
*/
iuxor(num) {
enforce(BN.isBN(num), 'num', 'bignum');
let a = this;
let b = num;
if (a.length < b.length)
[a, b] = [b, a];
let i = 0;
for (; i < b.length; i++)
this.words[i] = a.words[i] ^ b.words[i];
if (a !== this) {
this._alloc(a.length);
for (; i < a.length; i++)
this.words[i] = a.words[i];
}
this.length = a.length;
return this._strip();
}
iuxorn(num) {
enforce(isSMI(num), 'num', 'smi');
this.words[0] ^= Math.abs(num);
return this._normalize();
}
uxor(num) {
return this.clone().iuxor(num);
}
uxorn(num) {
return this.clone().iuxorn(num);
}
/*
* NOT
*/
inot() {
if (this.negative !== 0) {
// ~(-x) == ~(~(x-1)) == x-1
this.ineg().isubn(1);
} else {
// ~x == -x-1 == -(x+1)
this.iaddn(1).ineg();
}
return this;
}
not() {
return this.clone().inot();
}
inotn(width) {
enforce((width >>> 0) === width, 'width', 'uint32');
const r = width % 26;
let s = Math.ceil(width / 26);
let i = 0;
// Extend the buffer with leading zeroes.
this._expand(s);
if (r > 0)
s -= 1;
// Handle complete words.
for (; i < s; i++)
this.words[i] ^= 0x3ffffff;
// Handle the residue.
if (r > 0)
this.words[i] ^= (1 << r) - 1;
// And remove leading zeroes.
return this._strip();
}
notn(width) {
return this.clone().inotn(width);
}
/*
* Left Shift
*/
ishl(num) {
enforce(BN.isBN(num), 'bits', 'bignum');
enforce(num.bitLength() <= 32, 'bits', 'uint32');
return this.ishln(num.toNumber());
}
ishln(bits) {
return this.iushln(bits);
}
shl(num) {
return this.clone().ishl(num);
}
shln(bits) {
return this.clone().ishln(bits);
}
/*
* Unsigned Left Shift
*/
iushl(num) {
enforce(BN.isBN(num), 'bits', 'bignum');
enforce(num.bitLength() <= 32, 'bits', 'uint32');
return this.iushln(num.toNumber());
}
iushln(bits) {
enforce((bits >>> 0) === bits, 'bits', 'uint32');
const r = bits % 26;
const s = (bits - r) / 26;
const mask = ((1 << r) - 1) << (26 - r);
if (r !== 0) {
let carry = 0;
for (let i = 0; i < this.length; i++) {
const ncarry = this.words[i] & mask;
const c = ((this.words[i] | 0) - ncarry) << r;
this.words[i] = c | carry;
carry = ncarry >>> (26 - r);
}
if (carry !== 0) {
this._alloc(this.length + 1);
this.words[this.length++] = carry;
}
}
if (s !== 0) {
this._alloc(this.length + s);
for (let i = this.length - 1; i >= 0; i--)
this.words[i + s] = this.words[i];
for (let i = 0; i < s; i++)
this.words[i] = 0;
this.length += s;
}
return this._strip();
}
ushl(num) {
return this.clone().iushl(num);
}
ushln(bits) {
return this.clone().iushln(bits);
}
/*
* Right Shift Engine
*/
_split(bits, output) {
const r = bits % 26;
const s = Math.min((bits - r) / 26, this.length);
const mask = (1 << r) - 1;
// Extended mode, copy masked part.
if (output) {
output._alloc(s);
for (let i = 0; i < s; i++)
output.words[i] = this.words[i];
output.length = s;
}
if (s === 0) {
// No-op, we should not move anything at all.
} else if (this.length > s) {
this.length -= s;
for (let i = 0; i < this.length; i++)
this.words[i] = this.words[i + s];
} else {
this.words[0] = 0;
this.length = 1;
}
let carry = 0;
if (r !== 0) {
for (let i = this.length - 1; i >= 0; i--) {
const word = this.words[i] | 0;
this.words[i] = (carry << (26 - r)) | (word >>> r);
carry = word & mask;
}
}
// Push carried bits as a mask.
if (output) {
if (carry !== 0) {
output._alloc(output.length + 1);
output.words[output.length++] = carry;
} else {
if (output.length === 0)
output.words[output.length++] = 0;
output._strip();
}
}
return this._strip();
}
/*
* Right Shift
*/
ishr(num) {
enforce(BN.isBN(num), 'bits', 'bignum');
enforce(num.bitLength() <= 32, 'bits', 'uint32');
return this.ishrn(num.toNumber());
}
ishrn(bits) {
enforce((bits >>> 0) === bits, 'bits', 'uint32');
if (this.negative !== 0) {
// (-x) >> y == ~(x-1) >> y
// == ~((x-1) >> y)
// == -(((x-1) >> y) + 1)
this.iaddn(1);
this.iushrn(bits);
this.isubn(1);
return this;
}
return this.iushrn(bits);
}
shr(num) {
return this.clone().ishr(num);
}
shrn(bits) {
return this.clone().ishrn(bits);
}
/*
* Unsigned Right Shift
*/
iushr(num) {
enforce(BN.isBN(num), 'bits', 'bignum');
enforce(num.bitLength() <= 32, 'bits', 'uint32');
return this.iushrn(num.toNumber());
}
iushrn(bits) {
enforce((bits >>> 0) === bits, 'bits', 'uint32');
return this._split(bits, null);
}
ushr(num) {
return this.clone().iushr(num);
}
ushrn(bits) {
return this.clone().iushrn(bits);
}
/*
* Bit Manipulation
*/
setn(bit, val) {
enforce((bit >>> 0) === bit, 'bit', 'uint32');
if (this.negative !== 0) {
this.iaddn(1);
this.usetn(bit, !val);
this.isubn(1);
return this;
}
return this.usetn(bit, val);
}
usetn(bit, val) {
enforce((bit >>> 0) === bit, 'bit', 'uint32');
const r = bit % 26;
const s = (bit - r) / 26;
this._expand(s + 1);
if (val)
this.words[s] |= (1 << r);
else
this.words[s] &= ~(1 << r);
return this._strip();
}
testn(bit) {
enforce((bit >>> 0) === bit, 'bit', 'uint32');
const r = bit % 26;
const s = (bit - r) / 26;
// Fast case: bit is much higher than all existing words.
if (this.length <= s)
return this.negative;
// Check bit and return.
const w = this.words[s];
const val = (w >> r) & 1;
if (this.negative !== 0) {
if (r > 0 && (w & ((1 << r) - 1)))
return val ^ 1;
let j = s;
while (j--) {
if (this.words[j] > 0)
return val ^ 1;
}
}
return val;
}
utestn(bit) {
enforce((bit >>> 0) === bit, 'bit', 'uint32');
const r = bit % 26;
const s = (bit - r) / 26;
// Fast case: bit is much higher than all existing words.
if (this.length <= s)
return 0;
// Check bit and return.
return (this.words[s] >> r) & 1;
}
imaskn(bits) {
enforce((bits >>> 0) === bits, 'bits', 'uint32');
if (this.negative !== 0) {
this.iaddn(1);
this.inotn(bits + 1);
this.ineg();
}
return this.iumaskn(bits);
}
maskn(bits) {
return this.clone().imaskn(bits);
}
iumaskn(bits) {
enforce((bits >>> 0) === bits, 'bits', 'uint32');
const r = bits % 26;
let s = (bits - r) / 26;
if (this.length <= s)
return this;
if (r !== 0)
s += 1;
this.length = Math.min(s, this.length);
if (r !== 0)
this.words[this.length - 1] &= (1 << r) - 1;
if (this.length === 0)
this.words[this.length++] = 0;
return this._strip();
}
umaskn(bits) {
return this.clone().iumaskn(bits);
}
andln(num) {
return this.words[0] & num;
}
bit(pos) {
return this.utestn(pos);
}
bits(pos, width) {
enforce((pos >>> 0) === pos, 'pos', 'uint32');
enforce((width >>> 0) === width, 'width', 'uint32');
enforce(width <= 26, 'width', 'width');
const shift = pos % 26;
const index = (pos - shift) / 26;
if (index >= this.length)
return 0;
let bits = (this.words[index] >> shift) & ((1 << width) - 1);
if (shift + width > 26 && index + 1 < this.length) {
const more = shift + width - 26;
const next = this.words[index + 1] & ((1 << more) - 1);
bits |= next << (26 - shift);
}
return bits;
}
/*
* Negation
*/
ineg() {
if (!this.isZero())
this.negative ^= 1;
return this;
}
neg() {
return this.clone().ineg();
}
iabs() {
this.negative = 0;
return this;
}
abs() {
return this.clone().iabs();
}
/*
* Comparison
*/
cmp(num) {
enforce(BN.isBN(num), 'num', 'bignum');
if (this.negative !== num.negative)
return num.negative - this.negative;
const res = this.ucmp(num);
if (this.negative !== 0)
return -res | 0;
return res;
}
cmpn(num) {
enforce(isSMI(num), 'num', 'smi');
const negative = (num < 0) | 0;
if (this.negative !== negative)
return negative - this.negative;
const res = this.ucmpn(num);
if (this.negative !== 0)
return -res | 0;
return res;
}
eq(num) {
return this.cmp(num) === 0;
}
eqn(num) {
return this.cmpn(num) === 0;
}
gt(num) {
return this.cmp(num) > 0;
}
gtn(num) {
return this.cmpn(num) > 0;
}
gte(num) {
return this.cmp(num) >= 0;
}
gten(num) {
return this.cmpn(num) >= 0;
}
lt(num) {
return this.cmp(num) < 0;
}
ltn(num) {
return this.cmpn(num) < 0;
}
lte(num) {
return this.cmp(num) <= 0;
}
lten(num) {
return this.cmpn(num) <= 0;
}
sign() {
if (this.negative !== 0)
return -1;
if (this.length === 1 && this.words[0] === 0)
return 0;
return 1;
}
isZero() {
return this.length === 1 && this.words[0] === 0;
}
isNeg() {
return this.negative !== 0;
}
isPos() {
return this.negative === 0;
}
isOdd() {
return (this.words[0] & 1) === 1;
}
isEven() {
return (this.words[0] & 1) === 0;
}
/*
* Unsigned Comparison
*/
ucmp(num) {
enforce(BN.isBN(num), 'num', 'bignum');
if (this.length < num.length)
return -1;
if (this.length > num.length)
return 1;
for (let i = this.length - 1; i >= 0; i--) {
const a = this.words[i] | 0;
const b = num.words[i] | 0;
if (a === b)
continue;
return (a > b) - (a < b);
}
return 0;
}
ucmpn(num) {
enforce(isSMI(num), 'num', 'smi');
if (this.length > 1)
return 1;
const w = this.words[0] | 0;
if (num < 0)
num = -num;
return (w > num) - (w < num);
}
/*
* Number Theoretic Functions
*/
legendre(num) {
const red = HAS_BIGINT ? BN.red(num) : BN.mont(num);
return this.toRed(red).redLegendre();
}
jacobi(num) {
// See: A Binary Algorithm for the Jacobi Symbol
// J. Shallit, J. Sorenson
// Page 3, Section 3
enforce(BN.isBN(num), 'num', 'bignum');
if (num.isZero() || num.isEven())
throw new Error('jacobi: `num` must be odd.');
let a = this._cloneNormal();
let b = num.clone();
let j = 1;
if (b.isNeg()) {
if (a.isNeg())
j = -1;
b.ineg();
}
if (a.isNeg() || a.ucmp(b) >= 0)
a.imod(b);
while (!a.isZero()) {
const bits = a._makeOdd();
if (bits & 1) {
const bmod8 = b.andln(7);
if (bmod8 === 3 || bmod8 === 5)
j = -j;
}
if (a.ucmp(b) < 0) {
[a, b] = [b, a];
if (a.andln(3) === 3 && b.andln(3) === 3)
j = -j;
}
a._isub(a, b).iushrn(1);
const bmod8 = b.andln(7);
if (bmod8 === 3 || bmod8 === 5)
j = -j;
}
if (b.cmpn(1) !== 0)
return 0;
return j;
}
kronecker(num) {
enforce(BN.isBN(num), 'num', 'bignum');
const table = [
0, 1, 0, -1,
0, -1, 0, 1
];
let a = this._cloneNormal();
let b = num.clone();
let k = 1;
if (b.isZero())
return a.ucmpn(1) === 0 ? k : 0;
if (!a.isOdd() && !b.isOdd())
return 0;
const bits = b._makeOdd();
if (bits & 1)
k = table[a.andln(7)];
if (b.isNeg()) {
if (a.isNeg())
k = -k;
b.ineg();
}
while (!a.isZero()) {
const bits = a._makeOdd();
if (bits & 1)
k *= table[b.andln(7)];
const w = a.words[0] ^ (a.negative * 0x3ffffff);
if (w & b.words[0] & 2)
k = -k;
b.imod(a);
[a, b] = [b, a];
b.negative = 0;
}
if (b.cmpn(1) !== 0)
return 0;
return k;
}
igcd(num) {
return this.gcd(num)._move(this);
}
gcd(num) {
enforce(BN.isBN(num), 'num', 'bignum');
if (this.isZero())
return num.abs();
if (num.isZero())
return this.abs();
let a = this.clone();
let b = num.clone();
a.negative = 0;
b.negative = 0;
// Remove common factor of two.
const shift = a._factor2(b);
if (shift !== 0) {
a.iushrn(shift);
b.iushrn(shift);
}
for (;;) {
a._makeOdd();
b._makeOdd();
const cmp = a.ucmp(b);
if (cmp < 0) {
// a > b
[a, b] = [b, a];
} else if (cmp === 0 || b.ucmpn(1) === 0) {
// Break if a == b.
// Break if b == 1 to avoid repeated subtraction.
break;
}
a._isub(a, b);
}
return b.iushln(shift);
}
ilcm(num) {
return this.lcm(num)._move(this);
}
lcm(num) {
enforce(BN.isBN(num), 'num', 'bignum');
if (this.isZero() || num.isZero())
return new BN(0);
return this.quo(this.gcd(num)).mul(num).iabs();
}
egcd(num) {
enforce(BN.isBN(num), 'num', 'bignum');
if (this.isZero()) {
return [
new BN(0),
new BN(num.sign()),
num.abs()
];
}
if (num.isZero()) {
return [
new BN(this.sign()),
new BN(0),
this.abs()
];
}
const x = this.clone();
const y = num.clone();
x.negative = 0;
y.negative = 0;
// A * x + B * y = x
const A = new BN(1);
const B = new BN(0);
// C * x + D * y = y
const C = new BN(0);
const D = new BN(1);
// Remove common factor of two.
const g = x._factor2(y);
if (g > 0) {
x.iushrn(g);
y.iushrn(g);
}
const xp = x.clone();
const yp = y.clone();
while (!x.isZero()) {
let i = x._makeOdd();
let j = y._makeOdd();
while (i--) {
if (A.isOdd() || B.isOdd()) {
A.iadd(yp);
B.isub(xp);
}
A.iushrn(1);
B.iushrn(1);
}
while (j--) {
if (C.isOdd() || D.isOdd()) {
C.iadd(yp);
D.isub(xp);
}
C.iushrn(1);
D.iushrn(1);
}
if (x.cmp(y) >= 0) {
x.isub(y);
A.isub(C);
B.isub(D);
} else {
y.isub(x);
C.isub(A);
D.isub(B);
}
}
if (this.negative !== 0)
C.ineg();
if (num.negative !== 0)
D.ineg();
return [C, D, y.iushln(g)];
}
iinvert(num) {
return this.invert(num)._move(this);
}
invert(num) {
enforce(BN.isBN(num), 'num', 'bignum');
range(num.sign() > 0, 'invert');
if (num.isOdd())
return this._invertp(num);
if (num.cmpn(1) === 0)
throw new RangeError('Not invertible.');
const [s,, g] = this.egcd(num);
if (g.cmpn(1) !== 0)
throw new RangeError('Not invertible.');
return s.imod(num);
}
ifermat(num) {
return this.fermat(num)._move(this);
}
fermat(num) {
const red = HAS_BIGINT ? BN.red(num) : BN.mont(num);
return this.toRed(red).redFermat().fromRed();
}
ipowm(y, m, mont) {
return this.powm(y, m, mont)._move(this);
}
powm(y, m, mont) {
const red = !HAS_BIGINT && mont ? BN.mont(m) : BN.red(m);
return this.toRed(red).redPow(y).fromRed();
}
ipowmn(y, m, mont) {
return this.powmn(y, m, mont)._move(this);
}
powmn(y, m, mont) {
const red = mont ? BN.mont(m) : BN.red(m);
return this.toRed(red).redPown(y).fromRed();
}
isqrtm(p) {
return this.sqrtm(p)._move(this);
}
sqrtm(p) {
enforce(BN.isBN(p), 'p', 'bignum');
let red;
if (p.andln(3) === 3 || p.andln(7) === 5) {
// Probably not worth the setup.
red = BN.red(p);
} else {
red = BN.mont(p);
}
return this.toRed(red).redSqrt().fromRed();
}
isqrtpq(p, q) {
return this.sqrtpq(p, q)._move(this);
}
sqrtpq(p, q) {
const sp = this.sqrtm(p);
const sq = this.sqrtm(q);
const [mp, mq] = p.egcd(q);
const lhs = sq.mul(mp).mul(p);
const rhs = sp.mul(mq).mul(q);
const n = p.mul(q);
return lhs.iadd(rhs).imod(n);
}
/*
* Primality Testing
*/
isPrime(rng, reps, limit) {
enforce((reps >>> 0) === reps, 'reps', 'uint32');
if (!this.isPrimeMR(rng, reps + 1, true))
return false;
if (!this.isPrimeLucas(limit))
return false;
return true;
}
isPrimeMR(rng, reps, force2 = false) {
enforce((reps >>> 0) === reps, 'reps', 'uint32');
enforce(reps > 0, 'reps', 'integer');
enforce(typeof force2 === 'boolean', 'force2', 'boolean');
const n = this;
if (n.cmpn(7) < 0) {
return n.cmpn(2) === 0
|| n.cmpn(3) === 0
|| n.cmpn(5) === 0;
}
if (n.isEven())
return false;
const nm1 = n.subn(1);
const nm3 = nm1.subn(2);
const k = nm1.zeroBits();
const q = nm1.ushrn(k);
const red = BN.red(n);
const rnm1 = nm1.toRed(red);
const rone = new BN(1).toRed(red);
next:
for (let i = 0; i < reps; i++) {
let x;
if (i === reps - 1 && force2) {
x = new BN(2);
} else {
x = BN.random(rng, 0, nm3);
x.iaddn(2);
}
let y = x.toRed(red).redPow(q);
if (y.cmp(rone) === 0 || y.cmp(rnm1) === 0)
continue;
for (let j = 1; j < k; j++) {
y = y.redSqr();
if (y.cmp(rnm1) === 0)
continue next;
if (y.cmp(rone) === 0)
return false;
}
return false;
}
return true;
}
isPrimeLucas(limit = 0) {
enforce((limit >>> 0) === limit, 'limit', 'uint32');
const n = this;
// Ignore 0 and 1.
if (n.cmpn(1) <= 0)
return false;
// Two is the only even prime.
if (n.isEven())
return n.cmpn(2) === 0;
let p = 3;
for (;;) {
if (p > 10000) {
// Thought to be impossible.
throw new Error(`Cannot find (D/n) = -1 for ${n.toString(10)}.`);
}
if (limit !== 0 && p > limit) {
// Optional DoS limit.
return false;
}
const d = new BN(p * p - 4);
const j = d.jacobi(n);
if (j === -1)
break;
if (j === 0)
return n.cmpn(p + 2) === 0;
if (p === 40) {
if (n.isSquare())
return false;
}
p += 1;
}
const s = n.addn(1);
const r = s._makeOdd();
let vk = new BN(2);
let vk1 = new BN(p);
for (let i = s.bitLength(); i >= 0; i--) {
if (s.utestn(i)) {
vk = vk.mul(vk1).isubn(p).imod(n);
vk1 = vk1.sqr().isubn(2).imod(n);
} else {
vk1 = vk1.mul(vk).isubn(p).imod(n);
vk = vk.sqr().isubn(2).imod(n);
}
}
if (vk.cmpn(2) === 0 || vk.cmp(n.subn(2)) === 0) {
const a = vk.muln(p).imod(n);
const b = vk1.ushln(1).imod(n);
if (a.cmp(b) === 0)
return true;
}
for (let t = 0; t < r - 1; t++) {
if (vk.isZero())
return true;
if (vk.cmpn(2) === 0)
return false;
vk = vk.sqr().isubn(2).imod(n);
}
return false;
}
/*
* Twos Complement
*/
toTwos(width) {
if (this.negative !== 0)
return this.abs().inotn(width).iaddn(1);
return this.clone();
}
fromTwos(width) {
enforce((width >>> 0) === width, 'width', 'uint32');
range(width > 0, 'width');
if (this.testn(width - 1))
return this.notn(width).iaddn(1).ineg();
return this.clone();
}
/*
* Reduction Context
*/
toRed(ctx) {
enforce(ctx instanceof Red, 'ctx', 'reduction context');
if (this.red)
throw new Error('Already in reduction context.');
return ctx.convertTo(this);
}
fromRed() {
red(this.red, 'fromRed');
return this.red.convertFrom(this);
}
forceRed(ctx) {
enforce(ctx instanceof Red, 'ctx', 'reduction context');
if (this.red) {
if (!ctx.m.eq(this.red.m) || ctx.mont !== this.red.mont)
throw new Error('Already in reduction context.');
} else {
range(this.negative === 0, 'red');
range(this.ucmp(ctx.m) < 0, 'red');
}
return this.clone()._forceRed(ctx);
}
redIAdd(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redIAdd');
return this.red.iadd(this, num);
}
redAdd(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redAdd');
return this.red.add(this, num);
}
redIAddn(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redIAddn');
return this.red.iaddn(this, num);
}
redAddn(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redAddn');
return this.red.addn(this, num);
}
redISub(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redISub');
return this.red.isub(this, num);
}
redSub(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redSub');
return this.red.sub(this, num);
}
redISubn(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redISubn');
return this.red.isubn(this, num);
}
redSubn(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redSubn');
return this.red.subn(this, num);
}
redIMul(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redIMul');
return this.red.imul(this, num);
}
redMul(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redMul');
return this.red.mul(this, num);
}
redIMuln(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redIMuln');
return this.red.imuln(this, num);
}
redMuln(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redMuln');
return this.red.muln(this, num);
}
redIDiv(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redIDiv');
return this.red.idiv(this, num);
}
redDiv(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redDiv');
return this.red.div(this, num);
}
redIDivn(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redIDivn');
return this.red.idivn(this, num);
}
redDivn(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redDivn');
return this.red.divn(this, num);
}
redIPow(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redIPow');
nonred(!num.red, 'redIPow');
return this.red.ipow(this, num);
}
redPow(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redPow');
nonred(!num.red, 'redPow');
return this.red.pow(this, num);
}
redIPown(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redIPown');
return this.red.ipown(this, num);
}
redPown(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redPown');
return this.red.pown(this, num);
}
redISqr() {
red(this.red, 'redISqr');
return this.red.isqr(this);
}
redSqr() {
red(this.red, 'redSqr');
return this.red.sqr(this);
}
redISqrt() {
red(this.red, 'redISqrt');
return this.red.isqrt(this);
}
redSqrt() {
red(this.red, 'redSqrt');
return this.red.sqrt(this);
}
redIDivSqrt(v) {
red(this.red, 'redIDivSqrt');
return this.red.idivsqrt(this, v);
}
redDivSqrt(v) {
red(this.red, 'redDivSqrt');
return this.red.divsqrt(this, v);
}
redIsSquare() {
red(this.red, 'redIsSquare');
return this.red.isSquare(this);
}
redIShl(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redIShl');
nonred(!num.red, 'redIShl');
return this.red.ishl(this, num);
}
redShl(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redShl');
nonred(!num.red, 'redShl');
return this.red.shl(this, num);
}
redIShln(num) {
enforce((num >>> 0) === num, 'num', 'uint32');
red(this.red, 'redIShln');
return this.red.ishln(this, num);
}
redShln(num) {
enforce((num >>> 0) === num, 'num', 'uint32');
red(this.red, 'redShln');
return this.red.shln(this, num);
}
redINeg() {
red(this.red, 'redINeg');
return this.red.ineg(this);
}
redNeg() {
red(this.red, 'redNeg');
return this.red.neg(this);
}
redEq(num) {
enforce(BN.isBN(num), 'num', 'bignum');
red(this.red, 'redEq');
return this.red.eq(this, num);
}
redEqn(num) {
enforce(isSMI(num), 'num', 'smi');
red(this.red, 'redEqn');
return this.red.eqn(this, num);
}
redIsHigh() {
red(this.red, 'redIsHigh');
return this.red.isHigh(this);
}
redIsLow() {
red(this.red, 'redIsLow');
return this.red.isLow(this);
}
redIsOdd() {
red(this.red, 'redIsOdd');
return this.red.isOdd(this);
}
redIsEven() {
red(this.red, 'redIsEven');
return this.red.isEven(this);
}
redLegendre() {
red(this.red, 'redLegendre');
return this.red.legendre(this);
}
redJacobi() {
red(this.red, 'redJacobi');
return this.red.jacobi(this);
}
redKronecker() {
red(this.red, 'redKronecker');
return this.red.kronecker(this);
}
redIInvert() {
red(this.red, 'redIInvert');
return this.red.iinvert(this);
}
redInvert() {
red(this.red, 'redInvert');
return this.red.invert(this);
}
redIFermat() {
red(this.red, 'redIFermat');
return this.red.ifermat(this);
}
redFermat() {
red(this.red, 'redFermat');
return this.red.fermat(this);
}
/*
* Internal
*/
_move(dest) {
dest.words = this.words;
dest.length = this.length;
dest.negative = this.negative;
dest.red = this.red;
return dest;
}
_alloc(size) {
while (this.words.length < size)
this.words.push(0);
return this;
}
_expand(size) {
this._alloc(size);
while (this.length < size)
this.words[this.length++] = 0;
return this;
}
_strip() {
while (this.length > 1 && this.words[this.length - 1] === 0)
this.length -= 1;
return this._normalize();
}
_normalize() {
assert(this.length > 0);
// -0 = 0
if (this.length === 1 && this.words[0] === 0)
this.negative = 0;
return this;
}
_check() {
// We never have a zero length number.
assert(this.length > 0);
// Cannot exceed array bounds.
assert(this.length <= this.words.length);
if (this.length === 1) {
// Must be normalized.
if (this.words[0] === 0)
assert(this.negative === 0);
return this;
}
// Must be stripped.
assert(this.words[this.length - 1] !== 0);
return this;
}
_invertp(p) {
// Penk's right shift binary EGCD.
//
// See: The Art of Computer Programming,
// Volume 2, Seminumerical Algorithms
// Donald E. Knuth
// Exercise 4.5.2.39
enforce(BN.isBN(p), 'p', 'bignum');
range(p.sign() > 0, 'invert');
assert(p.isOdd());
if (p.cmpn(1) === 0)
throw new RangeError('Not invertible.');
const a = this.clone();
const b = p.clone();
const u = new BN(1);
const v = new BN(0);
if (a.isNeg() || a.ucmp(b) >= 0)
a.imod(b);
while (!a.isZero()) {
let i = a._makeOdd();
let j = b._makeOdd();
while (i--) {
if (u.isOdd())
u._iadd(u, p);
u.iushrn(1);
}
while (j--) {
if (v.isOdd())
v._iadd(v, p);
v.iushrn(1);
}
if (a.ucmp(b) >= 0) {
a._isub(a, b);
if (u.ucmp(v) < 0) {
u._isub(v, u);
u._isub(p, u);
} else {
u._isub(u, v);
}
} else {
b._isub(b, a);
if (v.ucmp(u) < 0) {
v._isub(u, v);
v._isub(p, v);
} else {
v._isub(v, u);
}
}
}
if (b.cmpn(1) !== 0)
throw new RangeError('Not invertible.');
assert(v.negative === 0);
assert(v.ucmp(p) < 0);
return v;
}
_makeOdd() {
const shift = this.zeroBits();
if (shift > 0)
this.iushrn(shift);
return shift;
}
_factor2(num) {
// Find common factor of two.
// Expects inputs to be non-zero.
if ((this.words[0] | num.words[0]) & 1)
return 0;
const len = Math.min(this.length, num.length);
let r = 0;
for (let i = 0; i < len; i++) {
const b = zeroBits(this.words[i] | num.words[i]);
r += b;
if (b !== 26)
break;
}
return r;
}
_cloneNormal() {
return this.red ? this.fromRed() : this.clone();
}
_forceRed(ctx) {
this.red = ctx;
return this;
}
/*
* Helpers
*/
clone() {
const copy = new BN();
copy.words = new Array(this.length);
for (let i = 0; i < this.length; i++)
copy.words[i] = this.words[i];
copy.length = this.length;
copy.negative = this.negative;
copy.red = this.red;
return copy;
}
inject(num) {
enforce(BN.isBN(num), 'num', 'bignum');
this._alloc(num.length);
for (let i = 0; i < num.length; i++)
this.words[i] = num.words[i];
this.length = num.length;
this.negative = num.negative;
this.red = num.red;
return this;
}
set(num, endian) {
return this.fromNumber(num, endian);
}
swap(num) {
enforce(BN.isBN(num), 'num', 'bignum');
const x = this;
const y = num;
[x.words, y.words] = [y.words, x.words];
[x.length, y.length] = [y.length, x.length];
[x.negative, y.negative] = [y.negative, x.negative];
[x.red, y.red] = [y.red, x.red];
return x;
}
reverse() {
const neg = this.negative;
this.fromBuffer(this.toBuffer('be'), 'le');
this.negative = neg;
return this;
}
byteLength() {
return Math.ceil(this.bitLength() / 8);
}
bitLength() {
const w = this.words[this.length - 1];
const hi = countBits(w);
return (this.length - 1) * 26 + hi;
}
zeroBits() {
if (this.isZero())
return 0;
if (this.isOdd())
return 0;
let r = 0;
for (let i = 0; i < this.length; i++) {
const b = zeroBits(this.words[i]);
r += b;
if (b !== 26)
break;
}
return r;
}
isSafe() {
if (this.length <= 2)
return true;
if (this.length === 3 && this.words[2] === 0x01)
return true;
return false;
}
word(pos) {
enforce((pos >>> 0) === pos, 'pos', 'uint32');
if (pos >= this.length)
return 0;
return this.words[pos];
}
[custom]() {
let prefix = 'BN';
if (this.red)
prefix = 'BN-R';
return `<${prefix}: ${this.toString(10)}>`;
}
/*
* Conversion
*/
toNumber() {
let num = this.words[0];
if (this.length === 2) {
num += this.words[1] * 0x4000000;
} else if (this.length === 3 && this.words[2] === 0x01) {
// Note: at this stage it is known that the top bit is set.
num += 0x10000000000000 + (this.words[1] * 0x4000000);
} else if (this.length > 2) {
throw new RangeError('Number can only safely store up to 53 bits.');
}
return this.negative !== 0 ? -num : num;
}
toDouble() {
let num = 0;
for (let i = this.length - 1; i >= 0; i--)
num = (num * 0x4000000) + this.words[i];
return this.negative !== 0 ? -num : num;
}
valueOf() {
return this.toDouble();
}
toBigInt() {
if (!HAS_BIGINT)
throw new Error('BigInt is not supported!');
const s52 = BigInt(52);
const s26 = BigInt(26);
let i = this.length - 1;
let num = BigInt(0);
for (; i >= 1; i -= 2) {
const hi = this.words[i] * 0x4000000;
const lo = this.words[i - 1];
num = (num << s52) | BigInt(hi + lo);
}
if (i >= 0)
num = (num << s26) | BigInt(this.words[0]);
return this.negative !== 0 ? -num : num;
}
toBool() {
return !this.isZero();
}
toString(base, padding) {
base = getBase(base);
if (padding == null)
padding = 0;
if (padding === 0)
padding = 1;
enforce((base >>> 0) === base, 'base', 'uint32');
enforce((padding >>> 0) === padding, 'padding', 'uint32');
if (base < 2 || base > 36)
throw new RangeError('Base ranges between 2 and 36.');
this._check();
if (base === 16) {
let out = '';
let off = 0;
let carry = 0;
for (let i = 0; i < this.length; i++) {
const w = this.words[i];
const word = (((w << off) | carry) & 0xffffff).toString(16);
carry = (w >>> (24 - off)) & 0xffffff;
if (carry !== 0 || i !== this.length - 1)
out = zeros[6 - word.length] + word + out;
else
out = word + out;
off += 2;
if (off >= 26) {
off -= 26;
i -= 1;
}
}
if (carry !== 0)
out = carry.toString(16) + out;
while (out.length % padding !== 0)
out = '0' + out;
if (this.negative !== 0)
out = '-' + out;
return out;
}
const groupSize = groupSizes[base - 1];
const groupBase = groupBases[base - 1];
const c = this.clone();
let out = '';
c.negative = 0;
while (!c.isZero()) {
const r = c.remrn(groupBase).toString(base);
c.iquon(groupBase);
if (!c.isZero())
out = zeros[groupSize - r.length] + r + out;
else
out = r + out;
}
if (this.isZero())
out = '0';
while (out.length % padding !== 0)
out = '0' + out;
if (this.negative !== 0)
out = '-' + out;
return out;
}
toJSON() {
return this.toString(16, 2);
}
toArray(endian, length) {
return this.toArrayLike(Array, endian, length);
}
toBuffer(endian, length) {
return this.toArrayLike(Buffer, endian, length);
}
toArrayLike(ArrayType, endian, length) {
if (endian == null)
endian = 'be';
if (length == null)
length = 0;
enforce(typeof ArrayType === 'function', 'ArrayType', 'function');
enforce(endian === 'be' || endian === 'le', 'endian', 'endianness');
enforce((length >>> 0) === length, 'length', 'uint32');
this._check();
const bytes = this.byteLength();
const size = length || Math.max(1, bytes);
if (bytes > size)
throw new RangeError('Byte array longer than desired length.');
const res = allocate(ArrayType, size);
// See: https://github.com/indutny/bn.js/pull/222
if (endian === 'be') {
let pos = res.length - 1;
let carry = 0;
for (let i = 0; i < this.length; i++) {
const shift = (i & 3) << 1;
const word = (this.words[i] << shift) | carry;
res[pos--] = word & 0xff;
if (pos >= 0)
res[pos--] = (word >>> 8) & 0xff;
if (pos >= 0)
res[pos--] = (word >>> 16) & 0xff;
if (shift === 6) {
if (pos >= 0)
res[pos--] = (word >>> 24) & 0xff;
carry = 0;
} else {
carry = word >>> 24;
}
}
if (pos >= 0) {
res[pos--] = carry;
while (pos >= 0)
res[pos--] = 0;
carry = 0;
}
assert(carry === 0);
} else {
let pos = 0;
let carry = 0;
for (let i = 0; i < this.length; i++) {
const shift = (i & 3) << 1;
const word = (this.words[i] << shift) | carry;
res[pos++] = word & 0xff;
if (pos < res.length)
res[pos++] = (word >>> 8) & 0xff;
if (pos < res.length)
res[pos++] = (word >>> 16) & 0xff;
if (shift === 6) {
if (pos < res.length)
res[pos++] = (word >>> 24) & 0xff;
carry = 0;
} else {
carry = word >>> 24;
}
}
if (pos < res.length) {
res[pos++] = carry;
while (pos < res.length)
res[pos++] = 0;
carry = 0;
}
assert(carry === 0);
}
return res;
}
encode(endian, length) {
return this.toBuffer(endian, length);
}
/*
* Instantiation
*/
of(num, endian) {
return this.fromNumber(num, endian);
}
fromNumber(num, endian) {
if (endian == null)
endian = 'be';
enforce(isInteger(num), 'num', 'integer');
enforce(endian === 'be' || endian === 'le', 'endian', 'endianness');
const neg = (num < 0) | 0;
if (neg)
num = -num;
if (num < 0x4000000) {
this.words[0] = num & 0x3ffffff;
this.length = 1;
} else if (num < 0x10000000000000) {
this.words = [
num & 0x3ffffff,
(num / 0x4000000) & 0x3ffffff
];
this.length = 2;
} else {
this.words = [
num & 0x3ffffff,
(num / 0x4000000) & 0x3ffffff,
1
];
this.length = 3;
}
this.negative = neg;
if (endian === 'le')
this.reverse();
return this;
}
fromDouble(num, endian) {
if (endian == null)
endian = 'be';
enforce(typeof num === 'number', 'num', 'double');
enforce(endian === 'be' || endian === 'le', 'endian', 'endianness');
if (!isFinite(num))
num = 0;
const neg = (num <= -1) | 0;
if (num < 0)
num = -num;
num = Math.floor(num);
this.words = [];
while (num > 0) {
const lo = num % 0x4000000;
const hi = (num - lo) / 0x4000000;
this.words.push(lo);
num = hi;
}
if (this.words.length === 0)
this.words.push(0);
this.length = this.words.length;
this.negative = neg;
if (endian === 'le')
this.reverse();
return this;
}
fromBigInt(num, endian) {
if (endian == null)
endian = 'be';
enforce(typeof num === 'bigint', 'num', 'bigint');
enforce(endian === 'be' || endian === 'le', 'endian', 'endianness');
if (!HAS_BIGINT)
throw new Error('BigInt is not supported!');
// You know the implementation has a
// problem when strings are twice
// as fast as bigints.
const start = (num < BigInt(0)) | 0;
this._fromHex(num.toString(16), start);
this.negative = start;
if (endian === 'le')
this.reverse();
return this;
}
fromBool(value) {
enforce(typeof value === 'boolean', 'value', 'boolean');
this.words[0] = value | 0;
this.length = 1;
this.negative = 0;
return this;
}
fromString(str, base, endian) {
if (base === 'le' || base === 'be')
[base, endian] = [endian, base];
base = getBase(base);
if (endian == null)
endian = 'be';
enforce(typeof str === 'string', 'string', 'string');
enforce((base >>> 0) === base, 'base', 'uint32');
enforce(endian === 'be' || endian === 'le', 'endian', 'endianness');
if (base < 2 || base > 36)
throw new Error('Base ranges between 2 and 36.');
str = str.replace(/\s+/g, '');
let start = 0;
if (str.length > 0 && str.charCodeAt(0) === 0x2d)
start = 1;
if (base === 16)
this._fromHex(str, start);
else
this._fromBase(str, base, start);
this.negative = start;
this._normalize();
if (endian === 'le')
this.reverse();
return this;
}
_fromHex(str, start) {
this.length = Math.max(2, Math.ceil((str.length - start) / 6));
this.words = new Array(this.length);
for (let i = 0; i < this.length; i++)
this.words[i] = 0;
// Scan 24-bit chunks and add them to the number.
let off = 0;
let i = str.length - 6;
let j = 0;
for (; i >= start; i -= 6) {
const w = parseHex(str, i, i + 6);
this.words[j] |= (w << off) & 0x3ffffff;
// `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb.
this.words[j + 1] |= (w >>> (26 - off)) & 0x3fffff;
off += 24;
if (off >= 26) {
off -= 26;
j += 1;
}
}
if (i + 6 !== start) {
const w = parseHex(str, start, i + 6);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] |= (w >>> (26 - off)) & 0x3fffff;
}
return this._strip();
}
_fromBase(str, base, start) {
// Initialize as zero.
this.words[0] = 0;
this.length = 1;
this.negative = 0;
// Find length of limb in base.
let limbLen = 0;
let limbPow = 1;
for (; limbPow <= 0x3ffffff; limbPow *= base)
limbLen += 1;
limbLen -= 1;
limbPow = (limbPow / base) | 0;
const total = str.length - start;
const mod = total % limbLen;
const end = Math.min(total, total - mod) + start;
let i = start;
for (; i < end; i += limbLen) {
const word = parseBase(str, i, i + limbLen, base);
this.imuln(limbPow);
this._iaddn(word);
}
if (mod !== 0) {
const pow = Math.pow(base, mod);
const word = parseBase(str, i, str.length, base);
this.imuln(pow);
this._iaddn(word);
}
return this;
}
fromJSON(json) {
if (BN.isBN(json)) {
if (json.red)
return json.fromRed();
return json.clone();
}
if (Array.isArray(json)) {
for (const chunk of json)
enforce(typeof chunk === 'string', 'chunk', 'string');
json = json.join('');
}
return this.fromString(json, 16);
}
fromBN(num) {
return this.inject(num);
}
fromArray(data, endian) {
enforce(Array.isArray(data), 'data', 'array');
return this.fromArrayLike(data, endian);
}
fromBuffer(data, endian) {
enforce(Buffer.isBuffer(data), 'data', 'buffer');
return this.fromArrayLike(data, endian);
}
fromArrayLike(data, endian) {
if (endian == null)
endian = 'be';
enforce(data && (data.length >>> 0) === data.length, 'data', 'array-like');
enforce(endian === 'be' || endian === 'le', 'endian', 'endianness');
if (data.length === 0) {
this.words[0] = 0;
this.length = 1;
this.negative = 0;
return this;
}
this.length = Math.max(2, Math.ceil(data.length / 3));
this.words = new Array(this.length);
this.negative = 0;
for (let i = 0; i < this.length; i++)
this.words[i] = 0;
const left = data.length % 3;
let off = 0;
let j = 0;
let w = 0;
if (endian === 'be') {
for (let i = data.length - 1; i >= 2; i -= 3) {
const w = data[i] | (data[i - 1] << 8) | (data[i - 2] << 16);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
off += 24;
if (off >= 26) {
off -= 26;
j += 1;
}
}
switch (left) {
case 2:
w = data[1] | (data[0] << 8);
break;
case 1:
w = data[0];
break;
}
} else {
const len = data.length - left;
for (let i = 0; i < len; i += 3) {
const w = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16);
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
off += 24;
if (off >= 26) {
off -= 26;
j += 1;
}
}
switch (left) {
case 2:
w = data[len] | (data[len + 1] << 8);
break;
case 1:
w = data[len];
break;
}
}
if (left > 0) {
this.words[j] |= (w << off) & 0x3ffffff;
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
}
return this._strip();
}
decode(data, endian) {
return this.fromBuffer(data, endian);
}
from(num, base, endian) {
if (num == null)
return this;
if (base === 'le' || base === 'be')
[base, endian] = [endian, base];
if (typeof num === 'number')
return this.fromNumber(num, endian);
if (typeof num === 'bigint')
return this.fromBigInt(num, endian);
if (typeof num === 'string')
return this.fromString(num, base, endian);
if (typeof num === 'object') {
if (BN.isBN(num))
return this.fromBN(num, endian);
if ((num.length >>> 0) === num.length)
return this.fromArrayLike(num, endian);
}
if (typeof num === 'boolean')
return this.fromBool(num);
throw new TypeError('Non-numeric object passed to BN.');
}
/*
* Static Methods
*/
static min(...args) {
let min = null;
for (const num of args) {
enforce(BN.isBN(num), 'num', 'bignum');
if (!min || num.cmp(min) < 0)
min = num;
}
return min || new BN(0);
}
static max(...args) {
let max = null;
for (const num of args) {
enforce(BN.isBN(num), 'num', 'bignum');
if (!max || num.cmp(max) > 0)
max = num;
}
return max || new BN(0);
}
static cmp(a, b) {
enforce(BN.isBN(a), 'a', 'bignum');
return a.cmp(b);
}
static ucmp(a, b) {
enforce(BN.isBN(a), 'a', 'bignum');
return a.ucmp(b);
}
static red(num) {
return new Red(num);
}
static barrett(num) {
return new Barrett(num);
}
static mont(num) {
return new Mont(num);
}
static _prime(name) {
if (primes[name])
return primes[name];
let prime;
if (name === 'p192')
prime = new P192();
else if (name === 'p224')
prime = new P224();
else if (name === 'p521')
prime = new P521();
else if (name === 'k256')
prime = new K256();
else if (name === 'p251')
prime = new P251();
else if (name === 'p25519')
prime = new P25519();
else if (name === 'p448')
prime = new P448();
else
throw new Error(`Unknown prime: "${name}".`);
primes[name] = prime;
return prime;
}
static prime(name) {
return BN._prime(name).p.clone();
}
static pow(num, exp) {
if (num === 2)
return BN.shift(1, exp);
return new BN().fromNumber(num).pown(exp);
}
static shift(num, bits) {
if (num === 1)
return new BN(0).usetn(bits, 1);
return new BN().fromNumber(num).ishln(bits);
}
static mask(bits) {
return BN.shift(1, bits).isubn(1);
}
static randomBits(rng, bits) {
enforce(rng != null, 'rng', 'rng');
enforce((bits >>> 0) === bits, 'bits', 'uint32');
if (typeof rng === 'object') {
enforce(typeof rng.randomBytes === 'function', 'rng', 'rng');
const size = (bits + 7) >>> 3;
const total = size * 8;
const bytes = rng.randomBytes(size);
enforce(Buffer.isBuffer(bytes), 'bytes', 'buffer');
if (bytes.length !== size)
throw new RangeError('Invalid number of bytes returned from RNG.');
const num = BN.fromBuffer(bytes);
if (total > bits)
num.iushrn(total - bits);
return num;
}
enforce(typeof rng === 'function', 'rng', 'rng');
const num = rng(bits);
enforce(BN.isBN(num), 'num', 'bignum');
range(num.negative === 0, 'RNG');
nonred(!num.red, 'RNG');
if (num.bitLength() > bits)
throw new RangeError('Invalid number of bits returned from RNG.');
return num;
}
static random(rng, min, max) {
min = BN.cast(min, 16);
max = BN.cast(max, 16);
if (min.cmp(max) > 0)
throw new RangeError('Minimum cannot be greater than maximum.');
const space = max.sub(min).iabs();
const bits = space.bitLength();
if (bits === 0)
return min.clone();
for (;;) {
const num = BN.randomBits(rng, bits);
// Maximum is _exclusive_!
if (num.cmp(space) >= 0)
continue;
// Minimum is _inclusive_!
num.iadd(min);
return num;
}
}
static of(num, endian) {
return new BN().of(num, endian);
}
static fromNumber(num, endian) {
return new BN().fromNumber(num, endian);
}
static fromDouble(num, endian) {
return new BN().fromDouble(num, endian);
}
static fromBigInt(num, endian) {
return new BN().fromBigInt(num, endian);
}
static fromBool(value) {
return new BN().fromBool(value);
}
static fromString(str, base, endian) {
return new BN().fromString(str, base, endian);
}
static fromJSON(json) {
return new BN().fromJSON(json);
}
static fromBN(num) {
return new BN().fromBN(num);
}
static fromArray(data, endian) {
return new BN().fromArray(data, endian);
}
static fromBuffer(data, endian) {
return new BN().fromBuffer(data, endian);
}
static fromArrayLike(data, endian) {
return new BN().fromArrayLike(data, endian);
}
static decode(data, endian) {
return new BN().decode(data, endian);
}
static from(num, base, endian) {
return new BN().from(num, base, endian);
}
static cast(num, base, endian) {
if (BN.isBN(num))
return num;
return new BN(num, base, endian);
}
static isBN(obj) {
return obj instanceof BN;
}
}
/*
* Static
*/
BN.BN = BN;
BN.wordSize = 26;
BN.native = 0;
/**
* Prime
*/
class Prime {
constructor(name, p) {
// P = 2^N - K
this.name = name;
this.p = new BN(p, 16);
this.n = this.p.bitLength();
this.k = BN.shift(1, this.n).isub(this.p);
this.lo = this.p.clone();
this.one = this.p.clone();
}
ireduce(num) {
// Assumes that `num` is less than `P^2`:
// num = HI * (2^N - K) + HI * K + LO = HI * K + LO (mod P)
const neg = num.negative !== 0;
// Track bits.
let bits = num.bitLength();
// Must be less than P^2.
assert(bits <= this.n * 2);
// Ensure positive.
num.negative = 0;
// Reduce.
while (bits > this.n) {
// lo = num & ((1 << n) - 1)
// num = num >> n
this.split(num, this.lo);
// num = num * K
this.imulK(num);
// num = num + lo
num._iadd(num, this.lo);
// bits = bitlen(num)
bits = num.bitLength();
}
// Final reduction.
const cmp = bits < this.n ? -1 : num.ucmp(this.p);
if (cmp === 0) {
num.words[0] = 0;
num.length = 1;
} else if (cmp > 0) {
num._isub(num, this.p);
} else {
// Note: we shouldn't need to strip here.
}
// Adjust sign.
if (neg && !num.isZero())
num._isub(this.p, num);
return num;
}
split(input, out) {
input._split(this.n, out);
}
imulK(num) {
return num.imul(this.k);
}
pm2(x1) {
// Exponent: p - 2
throw new Error('Not implemented.');
}
fermat(x) {
return this.pm2(x);
}
}
/**
* Prime (3 mod 4)
*/
class Prime34 extends Prime {
constructor(name, p) {
super(name, p);
}
pm3d4(x1) {
// Exponent: (p - 3) / 4
throw new Error('Not implemented.');
}
pp1d4(x1) {
// Exponent: (p + 1) / 4
throw new Error('Not implemented.');
}
sqrt(x) {
// r = x^((p + 1) / 4) mod p
const {red} = x;
const r = this.pp1d4(x);
if (!red.sqr(r).eq(x))
throw new SquareRootError(r);
return r;
}
divsqrt(u, v) {
// x = u^3 * v * (u^5 * v^3)^((p - 3) / 4) mod p
const {red} = u;
const u2 = red.sqr(u);
const u3 = red.mul(u2, u);
const u5 = red.mul(u3, u2);
const v3 = red.mul(red.sqr(v), v);
const p = this.pm3d4(red.mul(u5, v3));
const x = red.mul(red.mul(u3, v), p);
const c = red.mul(v, red.sqr(x));
if (c.eq(u))
return x;
throw new SquareRootError(x);
}
}
/**
* Prime (5 mod 8)
*/
class Prime58 extends Prime {
constructor(name, p, sm1) {
super(name, p);
this.sm1 = new BN(sm1, 16);
}
pm5d8(x1) {
// Exponent: (p - 5) / 8
throw new Error('Not implemented.');
}
pp3d8(x1) {
// Exponent: (p + 3) / 8
throw new Error('Not implemented.');
}
sqrt(x) {
// r = x^((p + 3) / 8) mod p
const {red} = x;
const sm1 = this.sm1._forceRed(red);
const r = this.pp3d8(x);
if (red.sqr(r).eq(x))
return r;
const c = red.mul(r, sm1);
if (red.sqr(c).eq(x))
return c;
throw new SquareRootError(r);
}
divsqrt(u, v) {
// x = u * v^3 * (u * v^7)^((p - 5) / 8) mod p
const {red} = u;
const sm1 = this.sm1._forceRed(red);
const v3 = red.mul(red.sqr(v), v);
const v7 = red.mul(red.sqr(v3), v);
const p = this.pm5d8(red.mul(u, v7));
const x = red.mul(red.mul(u, v3), p);
const c = red.mul(v, red.sqr(x));
if (c.eq(u))
return x;
const mc = red.ineg(c);
if (mc.eq(u))
return red.mul(x, sm1);
if (mc.eq(red.mul(u, sm1)))
throw new SquareRootError(red.mul(x, sm1));
throw new SquareRootError(x);
}
}
/**
* Prime (1 mod 16)
*/
class Prime116 extends Prime {
constructor(name, p, g) {
super(name, p);
this.g = new BN(g, 16);
this.z = this.p.subn(1).zeroBits();
}
powS(x1) {
// Exponent: (p - 1) / 2^k
throw new Error('Not implemented.');
}
powE(x1) {
// Exponent: (s + 1) / 2
throw new Error('Not implemented.');
}
sqrt(x) {
// Tonelli-Shanks (variable time).
//
// Constants:
//
// k = factors of 2 for (p - 1)
// s = (p - 1) / 2^k
// e = (s + 1) / 2
// n = first non-square in F(p)
//
// Algorithm:
//
// g = n^s mod p
// y = x^e mod p
// b = x^s mod p
//
// loop:
// t = b
// m = 0
//
// while t != 1:
// t = t^2 mod p
// m += 1
//
// if m == 0:
// break
//
// if m >= k:
// fail
//
// t = g^(2^(k - m - 1)) mod p
// g = t^2 mod p
// y = y * t mod p
// b = b * g mod p
// k = m
//
// return y
//
const {red} = x;
switch (red.jacobi(x)) {
case -1:
throw new SquareRootError(x);
case 0:
return x.clone();
case 1:
break;
}
let g = this.g._forceRed(red);
let y = this.powE(x);
let b = this.powS(x);
let k = this.z;
for (;;) {
let t = b;
let m = 0;
while (t.cmpn(1) !== 0 && m < k) {
t = red.sqr(t);
m += 1;
}
if (m === 0)
break;
assert(m < k);
t = red.sqrn(g, k - m - 1);
g = red.sqr(t);
y = red.mul(y, t);
b = red.mul(b, g);
k = m;
}
return y;
}
divsqrt(u, v) {
const {red} = u;
if (v.isZero())
throw new SquareRootError(v);
return this.sqrt(red.div(u, v));
}
}
/**
* P192
*/
class P192 extends Prime34 {
constructor() {
// 2^192 - 2^64 - 1 (= 3 mod 4)
super('p192', 'ffffffff ffffffff ffffffff fffffffe'
+ 'ffffffff ffffffff');
}
imulK(num) {
// K = 0x10000000000000001
// K = 2^64 + 1
const one = this.one.inject(num);
return num.iushln(64)._iadd(num, one);
}
core(x1) {
// Exponent: (p - 3) / 4
// Bits: 127x1 1x0 62x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const x3 = red.sqrnmul(x2, 1, x1);
const x6 = red.sqrnmul(x3, 3, x3);
const x12 = red.sqrnmul(x6, 6, x6);
const x24 = red.sqrnmul(x12, 12, x12);
const x30 = red.sqrnmul(x24, 6, x6);
const x31 = red.sqrnmul(x30, 1, x1);
const x62 = red.sqrnmul(x31, 31, x31);
const x124 = red.sqrnmul(x62, 62, x62);
const x127 = red.sqrnmul(x124, 3, x3);
const r0 = red.sqrn(x127, 1);
const r1 = red.sqrnmul(r0, 62, x62);
return r1;
}
pm3d4(x1) {
// Exponent: (p - 3) / 4
// Bits: 127x1 1x0 62x1
return this.core(x1);
}
pm2(x1) {
// Exponent: p - 2
// Bits: 127x1 1x0 62x1 1x0 1x1
const {red} = x1;
const r0 = this.core(x1);
const r1 = red.sqrn(r0, 1);
const r2 = red.sqrnmul(r1, 1, x1);
return r2;
}
pp1d4(x1) {
// Exponent: (p + 1) / 4
// Bits: 128x1 62x0
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const x4 = red.sqrnmul(x2, 2, x2);
const x8 = red.sqrnmul(x4, 4, x4);
const x16 = red.sqrnmul(x8, 8, x8);
const x32 = red.sqrnmul(x16, 16, x16);
const x64 = red.sqrnmul(x32, 32, x32);
const x128 = red.sqrnmul(x64, 64, x64);
const r0 = red.sqrn(x128, 62);
return r0;
}
}
/**
* P224
*/
class P224 extends Prime116 {
constructor() {
// 2^224 - 2^96 + 1 (1 mod 16)
super('p224', 'ffffffff ffffffff ffffffff ffffffff'
+ '00000000 00000000 00000001',
'6a0fec67 8598a792 0c55b2d4 0b2d6ffb'
+ 'bea3d8ce f3fb3632 dc691b74');
}
imulK(num) {
// K = 0xffffffffffffffffffffffff
// K = 2^96 - 1
const one = this.one.inject(num);
return num.iushln(96)._isub(num, one);
}
powS(x1) {
// Exponent: 2^128 - 1
// Bits: 128x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const x4 = red.sqrnmul(x2, 2, x2);
const x8 = red.sqrnmul(x4, 4, x4);
const x16 = red.sqrnmul(x8, 8, x8);
const x32 = red.sqrnmul(x16, 16, x16);
const x64 = red.sqrnmul(x32, 32, x32);
const x128 = red.sqrnmul(x64, 64, x64);
return x128;
}
powE(x1) {
// Exponent: 2^127
// Bits: 1x1 127x0
const {red} = x1;
const r0 = red.sqrn(x1, 127);
return r0;
}
pm2(x1) {
// Exponent: p - 2
// Bits: 127x1 1x0 96x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const x3 = red.sqrnmul(x2, 1, x1);
const x6 = red.sqrnmul(x3, 3, x3);
const x12 = red.sqrnmul(x6, 6, x6);
const x24 = red.sqrnmul(x12, 12, x12);
const x48 = red.sqrnmul(x24, 24, x24);
const x96 = red.sqrnmul(x48, 48, x48);
const x120 = red.sqrnmul(x96, 24, x24);
const x126 = red.sqrnmul(x120, 6, x6);
const x127 = red.sqrnmul(x126, 1, x1);
const r0 = red.sqrn(x127, 1);
const r1 = red.sqrnmul(r0, 96, x96);
return r1;
}
}
/**
* P521
*/
class P521 extends Prime34 {
constructor() {
// 2^521 - 1 (= 3 mod 4)
super('p521', '000001ff ffffffff ffffffff ffffffff'
+ 'ffffffff ffffffff ffffffff ffffffff'
+ 'ffffffff ffffffff ffffffff ffffffff'
+ 'ffffffff ffffffff ffffffff ffffffff'
+ 'ffffffff');
}
imulK(num) {
// K = 0x01
return num;
}
core(x1) {
// Exponent: 2^519 - 1
// Bits: 519x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const x3 = red.sqrnmul(x2, 1, x1);
const x6 = red.sqrnmul(x3, 3, x3);
const x7 = red.sqrnmul(x6, 1, x1);
const x8 = red.sqrnmul(x7, 1, x1);
const x16 = red.sqrnmul(x8, 8, x8);
const x32 = red.sqrnmul(x16, 16, x16);
const x64 = red.sqrnmul(x32, 32, x32);
const x128 = red.sqrnmul(x64, 64, x64);
const x256 = red.sqrnmul(x128, 128, x128);
const x512 = red.sqrnmul(x256, 256, x256);
const x519 = red.sqrnmul(x512, 7, x7);
return x519;
}
pm3d4(x1) {
// Exponent: 2^519 - 1
// Bits: 519x1
return this.core(x1);
}
pm2(x1) {
// Exponent: p - 2
// Bits: 519x1 1x0 1x1
const {red} = x1;
const r0 = this.core(x1);
const r1 = red.sqrn(r0, 1);
const r2 = red.sqrnmul(r1, 1, x1);
return r2;
}
pp1d4(x1) {
// Exponent: (p + 1) / 4
// Bits: 1x1 519x0
const {red} = x1;
const r0 = red.sqrn(x1, 519);
return r0;
}
}
/**
* K256
*/
class K256 extends Prime34 {
constructor() {
// 2^256 - 2^32 - 977 (= 3 mod 4)
super('k256', 'ffffffff ffffffff ffffffff ffffffff'
+ 'ffffffff ffffffff fffffffe fffffc2f');
}
split(input, output) {
// 256 = 9 * 26 + 22
const mask = 0x3fffff;
const len = Math.min(input.length, 9);
output._alloc(len + 1);
for (let i = 0; i < len; i++)
output.words[i] = input.words[i];
output.length = len;
if (input.length <= 9) {
output._strip();
input.words[0] = 0;
input.length = 1;
return;
}
// Shift by 9 limbs.
let prev = input.words[9];
let i = 10;
output.words[output.length++] = prev & mask;
output._strip();
for (; i < input.length; i++) {
const next = input.words[i] | 0;
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
prev = next;
}
prev >>>= 22;
input.words[i - 10] = prev;
if (prev === 0 && input.length > 10)
input.length -= 10;
else
input.length -= 9;
input._strip(); // Unsure if we need this.
}
imulK(num) {
// K = 0x1000003d1 = [0x40, 0x3d1]
// K = 2^32 + 977
num._expand(num.length + 2);
// Bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
let lo = 0;
for (let i = 0; i < num.length; i++) {
const w = num.words[i];
lo += w * 0x3d1;
num.words[i] = lo & 0x3ffffff;
lo = w * 0x40 + Math.floor(lo / 0x4000000);
}
// Fast length reduction.
if (num.words[num.length - 1] === 0) {
num.length -= 1;
if (num.words[num.length - 1] === 0)
num.length -= 1;
}
// Note: we shouldn't need to strip here.
return num;
}
core(x1, x2) {
// Exponent: (p - 47) / 64
// Bits: 223x1 1x0 22x1 4x0
const {red} = x1;
const x3 = red.sqrnmul(x2, 1, x1);
const x6 = red.sqrnmul(x3, 3, x3);
const x9 = red.sqrnmul(x6, 3, x3);
const x11 = red.sqrnmul(x9, 2, x2);
const x22 = red.sqrnmul(x11, 11, x11);
const x44 = red.sqrnmul(x22, 22, x22);
const x88 = red.sqrnmul(x44, 44, x44);
const x176 = red.sqrnmul(x88, 88, x88);
const x220 = red.sqrnmul(x176, 44, x44);
const x223 = red.sqrnmul(x220, 3, x3);
const r0 = red.sqrn(x223, 1);
const r1 = red.sqrnmul(r0, 22, x22);
const r2 = red.sqrn(r1, 4);
return r2;
}
pm3d4(x1) {
// Exponent: (p - 3) / 4
// Bits: 223x1 1x0 22x1 4x0 1x1 1x0 2x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const r2 = this.core(x1, x2);
const r3 = red.sqrnmul(r2, 1, x1);
const r4 = red.sqrn(r3, 1);
const r5 = red.sqrnmul(r4, 2, x2);
return r5;
}
pm2(x1) {
// Exponent: p - 2
// Bits: 223x1 1x0 22x1 4x0 1x1 1x0 2x1 1x0 1x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const r2 = this.core(x1, x2);
const r3 = red.sqrnmul(r2, 1, x1);
const r4 = red.sqrn(r3, 1);
const r5 = red.sqrnmul(r4, 2, x2);
const r6 = red.sqrn(r5, 1);
const r7 = red.sqrnmul(r6, 1, x1);
return r7;
}
pp1d4(x1) {
// Exponent: (p + 1) / 4
// Bits: 223x1 1x0 22x1 4x0 2x1 2x0
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const r2 = this.core(x1, x2);
const r3 = red.sqrnmul(r2, 2, x2);
const r4 = red.sqrn(r3, 2);
return r4;
}
}
/**
* P251
*/
class P251 extends Prime34 {
constructor() {
// 2^251 - 9
super('p251', '07ffffff ffffffff ffffffff ffffffff'
+ 'ffffffff ffffffff ffffffff fffffff7');
}
imulK(num) {
// K = 0x09
if (num.isZero())
return num;
let carry = 0;
for (let i = 0; i < num.length; i++) {
const w = num.words[i] * 0x09 + carry;
carry = w >>> 26;
num.words[i] = w & 0x3ffffff;
}
if (carry !== 0) {
num._alloc(num.length + 1);
num.words[num.length++] = carry;
}
// Note: we shouldn't need to strip here.
return num;
}
core(x1) {
// Exponent: 2^247 - 1
// Bits: 247x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const x3 = red.sqrnmul(x2, 1, x1);
const x6 = red.sqrnmul(x3, 3, x3);
const x12 = red.sqrnmul(x6, 6, x6);
const x24 = red.sqrnmul(x12, 12, x12);
const x48 = red.sqrnmul(x24, 24, x24);
const x96 = red.sqrnmul(x48, 48, x48);
const x192 = red.sqrnmul(x96, 96, x96);
const x240 = red.sqrnmul(x192, 48, x48);
const x246 = red.sqrnmul(x240, 6, x6);
const x247 = red.sqrnmul(x246, 1, x1);
return x247;
}
pm3d4(x1) {
// Exponent: (p - 3) / 4
// Bits: 247x1 1x0 1x1
const {red} = x1;
const r0 = this.core(x1);
const r1 = red.sqrn(r0, 1);
const r2 = red.sqrnmul(r1, 1, x1);
return r2;
}
pm2(x1) {
// Exponent: p - 2
// Bits: 247x1 1x0 1x1 1x0 1x1
const {red} = x1;
const r0 = this.core(x1);
const r1 = red.sqrn(r0, 1);
const r2 = red.sqrnmul(r1, 1, x1);
const r3 = red.sqrn(r2, 1);
const r4 = red.sqrnmul(r3, 1, x1);
return r4;
}
pp1d4(x1) {
// Exponent: (p + 1) / 4
// Bits: 248x1 1x0
const {red} = x1;
const r0 = this.core(x1);
const r1 = red.sqrnmul(r0, 1, x1);
const r2 = red.sqrn(r1, 1);
return r2;
}
}
/**
* P25519
*/
class P25519 extends Prime58 {
constructor() {
// 2^255 - 19 (= 5 mod 8)
super('p25519', '7fffffff ffffffff ffffffff ffffffff'
+ 'ffffffff ffffffff ffffffff ffffffed',
'2b832480 4fc1df0b 2b4d0099 3dfbd7a7'
+ '2f431806 ad2fe478 c4ee1b27 4a0ea0b0');
}
imulK(num) {
// K = 0x13
let carry = 0;
for (let i = 0; i < num.length; i++) {
const w = num.words[i] * 0x13 + carry;
carry = w >>> 26;
num.words[i] = w & 0x3ffffff;
}
if (carry !== 0) {
num._alloc(num.length + 1);
num.words[num.length++] = carry;
}
// Note: we shouldn't need to strip here.
return num;
}
core(x1, x2) {
// Exponent: 2^250 - 1
// Bits: 250x1
const {red} = x1;
const x4 = red.sqrnmul(x2, 2, x2);
const x5 = red.sqrnmul(x4, 1, x1);
const x10 = red.sqrnmul(x5, 5, x5);
const x20 = red.sqrnmul(x10, 10, x10);
const x40 = red.sqrnmul(x20, 20, x20);
const x50 = red.sqrnmul(x40, 10, x10);
const x100 = red.sqrnmul(x50, 50, x50);
const x200 = red.sqrnmul(x100, 100, x100);
const x250 = red.sqrnmul(x200, 50, x50);
return x250;
}
pm5d8(x1) {
// Exponent: (p - 5) / 8
// Bits: 250x1 1x0 1x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const r0 = this.core(x1, x2);
const r1 = red.sqrn(r0, 1);
const r2 = red.sqrnmul(r1, 1, x1);
return r2;
}
pm2(x1) {
// Exponent: p - 2
// Bits: 250x1 1x0 1x1 1x0 2x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const r0 = this.core(x1, x2);
const r1 = red.sqrn(r0, 1);
const r2 = red.sqrnmul(r1, 1, x1);
const r3 = red.sqrn(r2, 1);
const r4 = red.sqrnmul(r3, 2, x2);
return r4;
}
pp3d8(x1) {
// Exponent: (p + 3) / 8
// Bits: 251x1 1x0
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const r0 = this.core(x1, x2);
const r1 = red.sqrnmul(r0, 1, x1);
const r2 = red.sqrn(r1, 1);
return r2;
}
}
/**
* P448
*/
class P448 extends Prime34 {
constructor() {
// 2^448 - 2^224 - 1 (= 3 mod 4)
super('p448', 'ffffffff ffffffff ffffffff ffffffff'
+ 'ffffffff ffffffff fffffffe ffffffff'
+ 'ffffffff ffffffff ffffffff ffffffff'
+ 'ffffffff ffffffff');
}
imulK(num) {
// K = 0x100000000000000000000000000000000000000000000000000000001
// K = 2^224 + 1
const one = this.one.inject(num);
return num.iushln(224)._iadd(num, one);
}
core(x1, x2) {
// Exponent: 2^222 - 1
// Bits: 222x1
const {red} = x1;
const x3 = red.sqrnmul(x2, 1, x1);
const x6 = red.sqrnmul(x3, 3, x3);
const x9 = red.sqrnmul(x6, 3, x3);
const x11 = red.sqrnmul(x9, 2, x2);
const x22 = red.sqrnmul(x11, 11, x11);
const x44 = red.sqrnmul(x22, 22, x22);
const x88 = red.sqrnmul(x44, 44, x44);
const x176 = red.sqrnmul(x88, 88, x88);
const x220 = red.sqrnmul(x176, 44, x44);
const x222 = red.sqrnmul(x220, 2, x2);
return x222;
}
pm3d4(x1) {
// Exponent: (p - 3) / 4
// Bits: 223x1 1x0 222x1
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const x222 = this.core(x1, x2);
const r0 = red.sqrnmul(x222, 1, x1);
const r1 = red.sqrn(r0, 1);
const r2 = red.sqrnmul(r1, 222, x222);
return r2;
}
pm2(x1) {
// Exponent: p - 2
// Bits: 223x1 1x0 222x1 1x0 1x1
const {red} = x1;
const r0 = this.pm3d4(x1);
const r1 = red.sqrn(r0, 1);
const r2 = red.sqrnmul(r1, 1, x1);
return r2;
}
pp1d4(x1) {
// Exponent: (p + 1) / 4
// Bits: 224x1 222x0
const {red} = x1;
const x2 = red.sqrnmul(x1, 1, x1);
const r0 = this.core(x1, x2);
const r1 = red.sqrnmul(r0, 2, x2);
const r2 = red.sqrn(r1, 222);
return r2;
}
}
/**
* Reduction Engine
*/
class Red {
constructor(m) {
let prime = null;
if (typeof m === 'string') {
prime = BN._prime(m);
m = prime.p;
}
enforce(BN.isBN(m), 'm', 'bignum');
nonred(!m.red, 'reduction');
range(m.sign() > 0, 'reduction');
this.m = m;
this.prime = prime;
this.mb = null;
this.sm1 = null;
}
_verify1(a) {
range(a.negative === 0, 'red');
red(a.red != null, 'red');
}
_verify2(a, b) {
range((a.negative | b.negative) === 0, 'red');
red(a.red != null && a.red === b.red, 'red');
}
get mont() {
return false;
}
precompute() {
// Precompute `sqrt(-1)` for primes congruent to 5 mod 8.
if (this.sm1 === null && this.m.andln(7) === 5) {
if (this.prime) {
this.sm1 = this.prime.sm1.clone()._forceRed(this);
} else {
const x = new BN(2).toRed(this);
const e = this.m.subn(1).iushrn(2);
// sqrt(-1) = 2^((p - 1) / 4) mod p
this.sm1 = this.pow(x, e);
}
}
return this;
}
convertTo(num) {
const res = num.mod(this.m);
res.red = this;
return res;
}
convertFrom(num) {
const res = num.clone();
res.red = null;
return res;
}
intTo(a) {
return a;
}
intFrom(a) {
return a;
}
imod(a) {
if (this.prime)
return this.prime.ireduce(a)._forceRed(this);
return a.imod(this.m)._forceRed(this);
}
iadd(a, b) {
this._verify2(a, b);
a._iadd(a, b);
if (a.ucmp(this.m) >= 0)
a._isub(a, this.m);
return a;
}
add(a, b) {
if (a.length < b.length)
return this.iadd(b.clone(), a);
return this.iadd(a.clone(), b);
}
iaddn(a, num) {
this._verify1(a);
if (num < 0)
return this.isubn(a, -num);
if (this.m.length === 1)
num %= this.m.words[0];
a._iaddn(num);
if (a.ucmp(this.m) >= 0)
a._isub(a, this.m);
return a;
}
addn(a, num) {
return this.iaddn(a.clone(), num);
}
isub(a, b) {
this._verify2(a, b);
// 0: a - a mod m == 0
// -1: a - b mod m == m - (b - a)
// +1: a - b mod m == a - b
const cmp = a.ucmp(b);
if (cmp === 0) {
a.words[0] = 0;
a.length = 1;
return a;
}
if (cmp < 0) {
a._isub(b, a);
a._isub(this.m, a);
} else {
a._isub(a, b);
}
return a;
}
sub(a, b) {
return this.isub(a.clone(), b);
}
isubn(a, num) {
this._verify1(a);
if (num < 0)
return this.iaddn(a, -num);
if (this.m.length === 1)
num %= this.m.words[0];
// <: a - b mod m == m - (b - a)
// >=: a - b mod m == a - b
if (a.length === 1 && a.words[0] < num) {
a.words[0] = num - a.words[0];
a._isub(this.m, a);
} else {
a._isubn(num);
}
return a;
}
subn(a, num) {
return this.isubn(a.clone(), num);
}
imul(a, b) {
this._verify2(a, b);
return this.imod(a.imul(b));
}
mul(a, b) {
this._verify2(a, b);
return this.imod(a.mul(b));
}
imuln(a, num) {
this._verify1(a);
if (a.isZero())
return a;
if (num === 0) {
a.words[0] = 0;
a.length = 1;
return a;
}
const neg = num < 0;
if (neg)
num = -num;
if (this.m.length === 1)
num %= this.m.words[0];
a.imuln(num);
if (num <= 16) {
// Quick reduction.
while (a.ucmp(this.m) >= 0)
a._isub(a, this.m);
} else {
this.imod(a);
}
if (neg)
this.ineg(a);
return a;
}
muln(a, num) {
return this.imuln(a.clone(), num);
}
idiv(a, b) {
return this.div(a, b)._move(a);
}
div(a, b) {
return this.mul(a, this.invert(b));
}
idivn(a, num) {
return this.divn(a, num)._move(a);
}
divn(a, num) {
return this.div(a, this.convertTo(new BN(num)));
}
ipow(a, num) {
return this.pow(a, num)._move(a);
}
pow(a, num) {
this._verify1(a);
if (num.isNeg())
a = this.invert(a);
// Small exponent.
if (num.length === 1)
return this.pown(a, num.words[0]);
// Call out to BigInt.
if (HAS_BIGINT && !this.prime)
return this.powInt(a, num);
// Otherwise, a BN implementation.
return this.powNum(a, num);
}
powNum(a, num) {
// Sliding window (odd multiples only).
const one = new BN(1).toRed(this);
const wnd = new Array(WND_SIZE);
const a2 = this.sqr(a);
wnd[0] = a;
for (let i = 1; i < WND_SIZE; i++)
wnd[i] = this.mul(wnd[i - 1], a2);
let i = num.bitLength();
let r = one;
while (i >= WND_WIDTH) {
let width = WND_WIDTH;
let bits = num.bits(i - width, width);
if (bits < WND_SIZE) {
r = this.sqr(r);
i -= 1;
continue;
}
while ((bits & 1) === 0) {
width -= 1;
bits >>= 1;
}
if (r === one) {
r = wnd[bits >> 1].clone();
} else {
r = this.sqrn(r, width);
r = this.mul(r, wnd[bits >> 1]);
}
i -= width;
}
if (i > 0) {
const bits = num.bits(0, i);
while (i--) {
r = this.sqr(r);
if ((bits >> i) & 1)
r = this.mul(r, a);
}
}
return r;
}
powInt(a, num) {
if (this.mb === null)
this.mb = this.m.toBigInt();
const x = this.intFrom(a.toBigInt());
const y = powInt(x, num, this.mb);
const z = this.intTo(y);
return BN.fromBigInt(z)._forceRed(this);
}
sqrn(a, n) {
while (n--)
a = this.sqr(a);
return a;
}
sqrnmul(a, n, b) {
return this.mul(this.sqrn(a, n), b);
}
ipown(a, num) {
return this.pown(a, num)._move(a);
}
pown(a, num) {
this._verify1(a);
if (num < 0) {
a = this.invert(a);
num = -num;
}
if (num === 0)
return new BN(1).toRed(this);
if (num === 1)
return a.clone();
const bits = countBits(num);
let r = a;
for (let i = bits - 2; i >= 0; i--) {
r = this.sqr(r);
if ((num >> i) & 1)
r = this.mul(r, a);
}
return r;
}
isqr(a) {
return this.imul(a, a);
}
sqr(a) {
return this.mul(a, a);
}
isqrt(x) {
return this.sqrt(x)._move(x);
}
sqrt(x) {
this._verify1(x);
// Optimized square root chain.
if (this.prime)
return this.prime.sqrt(x);
// Fast case (p = 3 mod 4).
if (this.m.andln(3) === 3)
return this.sqrt3mod4(x);
// Fast case (p = 5 mod 8).
if (this.m.andln(7) === 5) {
if (this.sm1 != null)
return this.sqrt5mod8sm1(x);
return this.sqrt5mod8(x);
}
// Slow case (Tonelli-Shanks).
return this.sqrt0(x);
}
sqrt3mod4(x) {
const e = this.m.addn(1).iushrn(2); // (p + 1) / 4
const b = this.pow(x, e);
if (!this.sqr(b).eq(x))
throw new SquareRootError(b);
return b;
}
sqrt5mod8(x) {
// Atkin's Algorithm.
const one = new BN(1).toRed(this);
const e = this.m.ushrn(3); // (p - 5) / 8
const x2 = this.add(x, x);
const alpha = this.pow(x2, e);
const beta = this.mul(x2, this.sqr(alpha));
const b = this.mul(this.mul(alpha, x), this.isub(beta, one));
if (!this.sqr(b).eq(x))
throw new SquareRootError(b);
return b;
}
sqrt5mod8sm1(x) {
const e = this.m.addn(3).iushrn(3); // (p + 3) / 8
const b = this.pow(x, e);
if (this.sqr(b).eq(x))
return b;
const c = this.mul(b, this.sm1);
if (this.sqr(c).eq(x))
return c;
throw new SquareRootError(b);
}
sqrt0(x) {
if (this.m.cmpn(1) === 0 || !this.m.isOdd())
throw new Error('Invalid prime.');
switch (this.jacobi(x)) {
case -1:
throw new SquareRootError(x);
case 0:
return x.clone();
case 1:
break;
}
const one = new BN(1).toRed(this);
const s = this.m.subn(1);
const e = s._makeOdd();
const n = new BN(2).toRed(this);
while (this.jacobi(n) !== -1)
this.iadd(n, one);
let g = this.pow(n, s);
let b = this.pow(x, s);
let y = this.pow(x, s.iaddn(1).iushrn(1));
let k = e;
for (;;) {
let t = b;
let m = 0;
while (!t.eq(one) && m < k) {
t = this.sqr(t);
m += 1;
}
if (m === 0)
break;
assert(m < k);
t = this.sqrn(g, k - m - 1);
g = this.sqr(t);
y = this.mul(y, t);
b = this.mul(b, g);
k = m;
}
return y;
}
idivsqrt(u, v) {
return this.divsqrt(u, v)._move(u);
}
divsqrt(u, v) {
this._verify2(u, v);
// u = 0, v = 0
if (u.isZero() && v.isZero())
throw new SquareRootError(v);
// Optimized inverse square root chain.
if (this.prime)
return this.prime.divsqrt(u, v);
// p = 3 mod 4
if (this.m.andln(3) === 3)
return this.divsqrt3mod4(u, v);
// p = 5 mod 8
if (this.sm1 != null && this.m.andln(7) === 5)
return this.divsqrt5mod8(u, v);
// v = 0
if (v.isZero())
throw new SquareRootError(v);
return this.sqrt(this.div(u, v));
}
divsqrt3mod4(u, v) {
// x = u^3 * v * (u^5 * v^3)^((p - 3) / 4) mod p
const e = this.m.subn(3).iushrn(2);
const u2 = this.sqr(u);
const u3 = this.mul(u2, u);
const u5 = this.mul(u3, u2);
const v3 = this.mul(this.sqr(v), v);
const p = this.pow(this.mul(u5, v3), e);
const x = this.mul(this.mul(u3, v), p);
const c = this.mul(v, this.sqr(x));
if (c.eq(u))
return x;
throw new SquareRootError(x);
}
divsqrt5mod8(u, v) {
// x = u * v^3 * (u * v^7)^((p - 5) / 8) mod p
const e = this.m.subn(5).iushrn(3);
const v3 = this.mul(this.sqr(v), v);
const v7 = this.mul(this.sqr(v3), v);
const p = this.pow(this.mul(u, v7), e);
const x = this.mul(this.mul(u, v3), p);
const c = this.mul(v, this.sqr(x));
if (c.eq(u))
return x;
const mc = this.ineg(c);
if (mc.eq(u))
return this.mul(x, this.sm1);
if (mc.eq(this.mul(u, this.sm1)))
throw new SquareRootError(this.mul(x, this.sm1));
throw new SquareRootError(x);
}
isSquare(a) {
if (this.m.isOdd())
return this.jacobi(a) >= 0;
return this.kronecker(a) >= 0;
}
ishl(a, num) {
this._verify1(a);
return this.imod(a.iushl(num));
}
shl(a, num) {
return this.ishl(a.clone(), num);
}
ishln(a, num) {
this._verify1(a);
a.iushln(num);
if (num <= 4) {
// Quick reduction.
while (a.ucmp(this.m) >= 0)
a._isub(a, this.m);
} else {
this.imod(a);
}
return a;
}
shln(a, num) {
return this.ishln(a.clone(), num);
}
ineg(a) {
this._verify1(a);
if (!a.isZero())
a._isub(this.m, a);
return a;
}
neg(a) {
return this.ineg(a.clone());
}
eq(a, b) {
this._verify2(a, b);
return a.ucmp(b) === 0;
}
eqn(a, num) {
this._verify1(a);
if (this.m.length === 1) {
num %= this.m.words[0];
if (num < 0)
num += this.m.words[0];
return a.ucmpn(num) === 0;
}
if (num < 0) {
this.m._isubn(-num);
const cmp = a.ucmp(this.m);
this.m._iaddn(-num);
return cmp === 0;
}
return a.ucmpn(num) === 0;
}
isHigh(a) {
return !this.isLow(a);
}
isLow(a) {
this._verify1(a);
return a.ucmp(this.m.ushrn(1)) <= 0;
}
isOdd(a) {
this._verify1(a);
return a.isOdd();
}
isEven(a) {
this._verify1(a);
return a.isEven();
}
legendre(num) {
this._verify1(num);
if (this.m.isEven())
throw new Error('legendre: `num` must be odd.');
// Euler's criterion.
const e = this.m.subn(1).iushrn(1); // (p - 1) / 2
const symbol = this.pow(num, e);
if (symbol.isZero())
return 0;
const one = new BN(1).toRed(this);
if (symbol.eq(one))
return 1;
if (symbol.eq(this.ineg(one)))
return -1;
throw new Error('Invalid prime.');
}
jacobi(a) {
this._verify1(a);
return a.jacobi(this.m);
}
kronecker(a) {
this._verify1(a);
return a.kronecker(this.m);
}
iinvert(a) {
return this.invert(a)._move(a);
}
invert(a) {
this._verify1(a);
return a.invert(this.m)._forceRed(this);
}
ifermat(a) {
return this.fermat(a)._move(a);
}
fermat(a) {
this._verify1(a);
if (a.isZero() || this.m.cmpn(1) === 0)
throw new RangeError('Not invertible.');
// Optimized inversion chain.
if (this.prime)
return this.prime.fermat(a);
// Invert using fermat's little theorem.
return this.pow(a, this.m.subn(2));
}
invertAll(elems) {
// Montgomery's trick.
enforce(Array.isArray(elems), 'elems', 'array');
for (const elem of elems) {
enforce(BN.isBN(elem), 'elem', 'bignum');
this._verify1(elem);
}
if (this.m.cmpn(1) === 0 || this.m.isEven())
throw new RangeError('Not invertible.');
const len = elems.length;
const invs = new Array(len);
if (len === 0)
return invs;
let acc = new BN(1).toRed(this);
for (let i = 0; i < len; i++) {
if (elems[i].isZero()) {
invs[i] = elems[i].clone();
continue;
}
invs[i] = acc;
acc = this.mul(acc, elems[i]);
}
acc = this.invert(acc);
for (let i = len - 1; i >= 0; i--) {
if (elems[i].isZero())
continue;
invs[i] = this.mul(acc, invs[i]);
acc = this.mul(acc, elems[i]);
}
return invs;
}
[custom]() {
if (this.prime)
return `<Red: ${this.prime.name}>`;
return `<Red: ${this.m.toString(10)}>`;
}
}
/**
* Barrett Engine
*/
class Barrett extends Red {
constructor(m) {
super(m);
this.prime = null;
this.n = this.m.bitLength();
if ((this.n % 26) !== 0)
this.n += 26 - (this.n % 26);
this.k = this.n * 2;
this.w = this.k / 26;
this.b = BN.shift(1, this.k).div(this.m);
}
convertTo(num) {
if (num.length > this.w)
return super.convertTo(num);
return this.imod(num.clone());
}
_shift(q) {
let i = 0;
let j = this.w;
while (j < q.length)
q.words[i++] = q.words[j++];
if (i === 0)
q.words[i++] = 0;
q.length = i;
}
imod(a) {
const neg = a.negative;
assert(a.length <= this.w);
a.negative = 0;
const q = a.mul(this.b);
// Shift right by `k` bits.
this._shift(q);
a._isub(a, q.mul(this.m));
if (a.ucmp(this.m) >= 0)
a._isub(a, this.m);
if (neg && !a.isZero())
a._isub(this.m, a);
a.red = this;
return a;
}
}
/**
* Montgomery Engine
*/
class Mont extends Red {
constructor(m) {
super(m);
// Note that:
//
// mi = (-m^-1 mod (2^(n * 2))) mod r
//
// and:
//
// mi = (((2^n)^-1 mod m) * r^-1 - 1) / m
//
// are equivalent.
this.prime = null;
this.n = this.m.length * 26;
this.r = BN.shift(1, this.n);
this.r2 = BN.shift(1, this.n * 2).imod(this.m);
this.ri = this.r.invert(this.m);
this.mi = this.r.mul(this.ri).isubn(1).div(this.m);
this.rib = null;
}
get mont() {
return true;
}
convertTo(num) {
if (num.isNeg() || num.ucmp(this.m) >= 0)
return this.imod(num.ushln(this.n));
// Equivalent to: (num * 2^n) mod m
return this.mul(num, this.r2);
}
convertFrom(num) {
// Equivalent to: num * r^-1 mod m
const r = this.mul(num, new BN(1));
r.red = null;
return r;
}
intTo(a) {
return (a << BigInt(this.n)) % this.mb;
}
intFrom(a) {
if (this.rib === null)
this.rib = this.ri.toBigInt();
return (a * this.rib) % this.mb;
}
iaddn(a, num) {
return this.iadd(a, this.convertTo(new BN(num)));
}
isubn(a, num) {
return this.isub(a, this.convertTo(new BN(num)));
}
imul(a, b) {
return this.mul(a, b)._move(a);
}
mul(a, b) {
if (a.isZero() || b.isZero())
return new BN(0)._forceRed(this);
const t = a.mul(b);
const c = t.umaskn(this.n).mul(this.mi).iumaskn(this.n);
const u = t.iadd(c.mul(this.m)).iushrn(this.n);
if (u.ucmp(this.m) >= 0)
u._isub(u, this.m);
return u._forceRed(this);
}
imuln(a, num) {
this._verify1(a);
if (a.isZero())
return a;
if (num === 0) {
a.words[0] = 0;
a.length = 1;
return a;
}
const neg = num < 0;
if (neg)
num = -num;
if (this.m.length === 1)
num %= this.m.words[0];
const bits = countBits(num);
// Potentially compute with additions.
// This avoids an expensive division.
if (bits > 5) {
// Slow case (num > 31).
this.imul(a, this.convertTo(new BN(num)));
} else if ((num & (num - 1)) === 0) {
// Optimize for powers of two.
for (let i = 0; i < bits - 1; i++)
this.iadd(a, a);
} else {
// Multiply left to right.
const c = a.clone();
for (let i = bits - 2; i >= 0; i--) {
this.iadd(a, a);
if ((num >> i) & 1)
this.iadd(a, c);
}
}
if (neg)
this.ineg(a);
return a;
}
eqn(a, num) {
this._verify1(a);
if (num === 0)
return a.isZero();
return a.ucmp(this.convertTo(new BN(num))) === 0;
}
isLow(a) {
this._verify1(a);
return this.convertFrom(a).ucmp(this.m.ushrn(1)) <= 0;
}
isOdd(a) {
this._verify1(a);
return this.convertFrom(a).isOdd();
}
isEven(a) {
this._verify1(a);
return this.convertFrom(a).isEven();
}
invert(a) {
this._verify1(a);
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
return this.imod(a.invert(this.m).mul(this.r2));
}
}
/*
* Helpers
*/
function makeError(Error, msg, start) {
const err = new Error(msg);
if (Error.captureStackTrace)
Error.captureStackTrace(err, start);
return err;
}
function assert(value, message) {
if (!value) {
const msg = message || 'Assertion failed.';
throw makeError(Error, msg, assert);
}
}
function enforce(value, name, type) {
if (!value) {
const msg = `"${name}" must be a(n) ${type}.`;
throw makeError(TypeError, msg, enforce);
}
}
function range(value, name) {
if (!value) {
const msg = `"${name}" only works with positive numbers.`;
throw makeError(RangeError, msg, range);
}
}
function red(value, name) {
if (!value) {
const msg = `"${name}" only works with red numbers.`;
throw makeError(TypeError, msg, red);
}
}
function nonred(value, name) {
if (!value) {
const msg = `"${name}" only works with normal numbers.`;
throw makeError(TypeError, msg, nonred);
}
}
function nonzero(value) {
if (!value) {
const msg = 'Cannot divide by zero.';
throw makeError(RangeError, msg, nonzero);
}
}
class SquareRootError extends Error {
constructor(result) {
super();
this.name = 'SquareRootError';
this.message = 'X is not a square mod P.';
this.result = result.fromRed();
if (Error.captureStackTrace)
Error.captureStackTrace(this, SquareRootError);
}
}
function isInteger(num) {
return Number.isSafeInteger(num);
}
function isSMI(num) {
return isInteger(num)
&& num >= -0x3ffffff
&& num <= 0x3ffffff;
}
function allocate(ArrayType, size) {
if (ArrayType.allocUnsafeSlow)
return ArrayType.allocUnsafeSlow(size);
return new ArrayType(size);
}
function getBase(base) {
if (base == null)
return 10;
if (typeof base === 'number')
return base;
switch (base) {
case 'bin':
return 2;
case 'oct':
return 8;
case 'dec':
return 10;
case 'hex':
return 16;
}
return 0;
}
/*
* Internal
*/
function countBits(w) {
if (Math.clz32)
return 32 - Math.clz32(w);
let t = w;
let r = 0;
if (t >= 0x1000) {
r += 13;
t >>>= 13;
}
if (t >= 0x40) {
r += 7;
t >>>= 7;
}
if (t >= 0x8) {
r += 4;
t >>>= 4;
}
if (t >= 0x02) {
r += 2;
t >>>= 2;
}
return r + t;
}
function zeroBits(w) {
// Shortcut.
if (w === 0)
return 26;
let t = w;
let r = 0;
if ((t & 0x1fff) === 0) {
r += 13;
t >>>= 13;
}
if ((t & 0x7f) === 0) {
r += 7;
t >>>= 7;
}
if ((t & 0xf) === 0) {
r += 4;
t >>>= 4;
}
if ((t & 0x3) === 0) {
r += 2;
t >>>= 2;
}
if ((t & 0x1) === 0)
r += 1;
return r;
}
function parseHex(str, start, end) {
const len = Math.min(str.length, end);
let r = 0;
let z = 0;
for (let i = start; i < len; i++) {
const c = str.charCodeAt(i) - 48;
r <<= 4;
let b;
if (c >= 49 && c <= 54) {
// 'a' - 'f'
b = c - 49 + 0xa;
} else if (c >= 17 && c <= 22) {
// 'A' - 'F'
b = c - 17 + 0xa;
} else {
// '0' - '9'
b = c;
}
r |= b;
z |= b;
}
if (z & ~15)
throw new Error('Invalid string.');
return r;
}
function parseBase(str, start, end, mul) {
const len = Math.min(str.length, end);
let r = 0;
for (let i = start; i < len; i++) {
const c = str.charCodeAt(i) - 48;
r *= mul;
let b;
if (c >= 49) {
// 'a'
b = c - 49 + 0xa;
} else if (c >= 17) {
// 'A'
b = c - 17 + 0xa;
} else {
// '0' - '9'
b = c;
}
if (c < 0 || c > 207 || b >= mul)
throw new Error('Invalid string.');
r += b;
}
return r;
}
/*
* Exponentiation (bigint)
*/
function powInt(x, e, m) {
// Sliding window (odd multiples only).
const one = BigInt(1);
const wnd = new Array(WND_SIZE);
const x2 = (x * x) % m;
wnd[0] = x;
for (let i = 1; i < WND_SIZE; i++)
wnd[i] = (wnd[i - 1] * x2) % m;
let i = e.bitLength();
let r = one;
while (i >= WND_WIDTH) {
let width = WND_WIDTH;
let bits = e.bits(i - width, width);
if (bits < WND_SIZE) {
r = (r * r) % m;
i -= 1;
continue;
}
while ((bits & 1) === 0) {
width -= 1;
bits >>= 1;
}
if (r === one) {
r = wnd[bits >> 1];
} else {
r = sqrn(r, width, m);
r = (r * wnd[bits >> 1]) % m;
}
i -= width;
}
if (i > 0) {
const bits = e.bits(0, i);
while (i--) {
r = (r * r) % m;
if ((bits >> i) & 1)
r = (r * x) % m;
}
}
return r;
}
function sqrn(x, n, m) {
for (let i = 0; i < n; i++)
x = (x * x) % m;
return x;
}
/*
* Multiplication
*/
function smallMulTo(self, num, out) {
const len = self.length + num.length;
out.negative = self.negative ^ num.negative;
out._alloc(len);
out.length = len;
// Peel one iteration (compiler can't
// do it, because of code complexity).
const a = self.words[0];
const b = num.words[0];
const r = a * b;
const lo = r & 0x3ffffff;
let carry = (r / 0x4000000) | 0;
let k = 1;
out.words[0] = lo;
for (; k < out.length - 1; k++) {
// Sum all words with the same
// `i + j = k` and accumulate
// `ncarry`, note that ncarry
// could be >= 0x3ffffff.
let ncarry = carry >>> 26;
let rword = carry & 0x3ffffff;
const min = Math.max(0, k - self.length + 1);
const max = Math.min(k, num.length - 1);
for (let j = min; j <= max; j++) {
const i = k - j;
const a = self.words[i];
const b = num.words[j];
const r = a * b + rword;
ncarry += (r / 0x4000000) | 0;
rword = r & 0x3ffffff;
}
out.words[k] = rword | 0;
carry = ncarry | 0;
}
if (carry !== 0)
out.words[k] = carry | 0;
else
out.length -= 1;
return out._strip();
}
function bigMulTo(self, num, out) {
const len = self.length + num.length;
out.negative = self.negative ^ num.negative;
out._alloc(len);
out.length = len;
let carry = 0;
let hncarry = 0;
let k = 0;
for (; k < out.length - 1; k++) {
// Sum all words with the same
// `i + j = k` and accumulate
// `ncarry`, note that ncarry
// could be >= 0x3ffffff.
let ncarry = hncarry;
hncarry = 0;
let rword = carry & 0x3ffffff;
const min = Math.max(0, k - self.length + 1);
const max = Math.min(k, num.length - 1);
for (let j = min; j <= max; j++) {
const i = k - j;
const a = self.words[i];
const b = num.words[j];
const r = a * b;
let lo = r & 0x3ffffff;
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
lo = (lo + rword) | 0;
rword = lo & 0x3ffffff;
ncarry = (ncarry + (lo >>> 26)) | 0;
hncarry += ncarry >>> 26;
ncarry &= 0x3ffffff;
}
out.words[k] = rword;
carry = ncarry;
ncarry = hncarry;
}
if (carry !== 0)
out.words[k] = carry;
else
out.length -= 1;
return out._strip();
}
function jumboMulTo(x, y, out) {
// v8 has a 2147483519 bit max (~256mb).
if (!HAS_BIGINT || x.length + y.length > 82595519)
return bigMulTo(x, y, out);
const zero = BigInt(0);
const mask = BigInt(0x3ffffff);
const shift = BigInt(26);
let z = x.toBigInt() * y.toBigInt();
const neg = (z < zero) | 0;
if (neg)
z = -z;
let i = 0;
while (z > zero) {
out.words[i++] = Number(z & mask);
z >>= shift;
}
if (i === 0)
out.words[i++] = 0;
out.length = i;
out.negative = neg;
return out;
}
function comb10MulTo(self, num, out) {
const a = self.words;
const b = num.words;
const o = out.words;
const a0 = a[0] | 0;
const al0 = a0 & 0x1fff;
const ah0 = a0 >>> 13;
const a1 = a[1] | 0;
const al1 = a1 & 0x1fff;
const ah1 = a1 >>> 13;
const a2 = a[2] | 0;
const al2 = a2 & 0x1fff;
const ah2 = a2 >>> 13;
const a3 = a[3] | 0;
const al3 = a3 & 0x1fff;
const ah3 = a3 >>> 13;
const a4 = a[4] | 0;
const al4 = a4 & 0x1fff;
const ah4 = a4 >>> 13;
const a5 = a[5] | 0;
const al5 = a5 & 0x1fff;
const ah5 = a5 >>> 13;
const a6 = a[6] | 0;
const al6 = a6 & 0x1fff;
const ah6 = a6 >>> 13;
const a7 = a[7] | 0;
const al7 = a7 & 0x1fff;
const ah7 = a7 >>> 13;
const a8 = a[8] | 0;
const al8 = a8 & 0x1fff;
const ah8 = a8 >>> 13;
const a9 = a[9] | 0;
const al9 = a9 & 0x1fff;
const ah9 = a9 >>> 13;
const b0 = b[0] | 0;
const bl0 = b0 & 0x1fff;
const bh0 = b0 >>> 13;
const b1 = b[1] | 0;
const bl1 = b1 & 0x1fff;
const bh1 = b1 >>> 13;
const b2 = b[2] | 0;
const bl2 = b2 & 0x1fff;
const bh2 = b2 >>> 13;
const b3 = b[3] | 0;
const bl3 = b3 & 0x1fff;
const bh3 = b3 >>> 13;
const b4 = b[4] | 0;
const bl4 = b4 & 0x1fff;
const bh4 = b4 >>> 13;
const b5 = b[5] | 0;
const bl5 = b5 & 0x1fff;
const bh5 = b5 >>> 13;
const b6 = b[6] | 0;
const bl6 = b6 & 0x1fff;
const bh6 = b6 >>> 13;
const b7 = b[7] | 0;
const bl7 = b7 & 0x1fff;
const bh7 = b7 >>> 13;
const b8 = b[8] | 0;
const bl8 = b8 & 0x1fff;
const bh8 = b8 >>> 13;
const b9 = b[9] | 0;
const bl9 = b9 & 0x1fff;
const bh9 = b9 >>> 13;
let c = 0;
let lo, mid, hi;
out.negative = self.negative ^ num.negative;
out._alloc(20);
out.length = 19;
/* k = 0 */
lo = Math.imul(al0, bl0);
mid = Math.imul(al0, bh0);
mid = (mid + Math.imul(ah0, bl0)) | 0;
hi = Math.imul(ah0, bh0);
let w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
w0 &= 0x3ffffff;
/* k = 1 */
lo = Math.imul(al1, bl0);
mid = Math.imul(al1, bh0);
mid = (mid + Math.imul(ah1, bl0)) | 0;
hi = Math.imul(ah1, bh0);
lo = (lo + Math.imul(al0, bl1)) | 0;
mid = (mid + Math.imul(al0, bh1)) | 0;
mid = (mid + Math.imul(ah0, bl1)) | 0;
hi = (hi + Math.imul(ah0, bh1)) | 0;
let w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
w1 &= 0x3ffffff;
/* k = 2 */
lo = Math.imul(al2, bl0);
mid = Math.imul(al2, bh0);
mid = (mid + Math.imul(ah2, bl0)) | 0;
hi = Math.imul(ah2, bh0);
lo = (lo + Math.imul(al1, bl1)) | 0;
mid = (mid + Math.imul(al1, bh1)) | 0;
mid = (mid + Math.imul(ah1, bl1)) | 0;
hi = (hi + Math.imul(ah1, bh1)) | 0;
lo = (lo + Math.imul(al0, bl2)) | 0;
mid = (mid + Math.imul(al0, bh2)) | 0;
mid = (mid + Math.imul(ah0, bl2)) | 0;
hi = (hi + Math.imul(ah0, bh2)) | 0;
let w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
w2 &= 0x3ffffff;
/* k = 3 */
lo = Math.imul(al3, bl0);
mid = Math.imul(al3, bh0);
mid = (mid + Math.imul(ah3, bl0)) | 0;
hi = Math.imul(ah3, bh0);
lo = (lo + Math.imul(al2, bl1)) | 0;
mid = (mid + Math.imul(al2, bh1)) | 0;
mid = (mid + Math.imul(ah2, bl1)) | 0;
hi = (hi + Math.imul(ah2, bh1)) | 0;
lo = (lo + Math.imul(al1, bl2)) | 0;
mid = (mid + Math.imul(al1, bh2)) | 0;
mid = (mid + Math.imul(ah1, bl2)) | 0;
hi = (hi + Math.imul(ah1, bh2)) | 0;
lo = (lo + Math.imul(al0, bl3)) | 0;
mid = (mid + Math.imul(al0, bh3)) | 0;
mid = (mid + Math.imul(ah0, bl3)) | 0;
hi = (hi + Math.imul(ah0, bh3)) | 0;
let w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
w3 &= 0x3ffffff;
/* k = 4 */
lo = Math.imul(al4, bl0);
mid = Math.imul(al4, bh0);
mid = (mid + Math.imul(ah4, bl0)) | 0;
hi = Math.imul(ah4, bh0);
lo = (lo + Math.imul(al3, bl1)) | 0;
mid = (mid + Math.imul(al3, bh1)) | 0;
mid = (mid + Math.imul(ah3, bl1)) | 0;
hi = (hi + Math.imul(ah3, bh1)) | 0;
lo = (lo + Math.imul(al2, bl2)) | 0;
mid = (mid + Math.imul(al2, bh2)) | 0;
mid = (mid + Math.imul(ah2, bl2)) | 0;
hi = (hi + Math.imul(ah2, bh2)) | 0;
lo = (lo + Math.imul(al1, bl3)) | 0;
mid = (mid + Math.imul(al1, bh3)) | 0;
mid = (mid + Math.imul(ah1, bl3)) | 0;
hi = (hi + Math.imul(ah1, bh3)) | 0;
lo = (lo + Math.imul(al0, bl4)) | 0;
mid = (mid + Math.imul(al0, bh4)) | 0;
mid = (mid + Math.imul(ah0, bl4)) | 0;
hi = (hi + Math.imul(ah0, bh4)) | 0;
let w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
w4 &= 0x3ffffff;
/* k = 5 */
lo = Math.imul(al5, bl0);
mid = Math.imul(al5, bh0);
mid = (mid + Math.imul(ah5, bl0)) | 0;
hi = Math.imul(ah5, bh0);
lo = (lo + Math.imul(al4, bl1)) | 0;
mid = (mid + Math.imul(al4, bh1)) | 0;
mid = (mid + Math.imul(ah4, bl1)) | 0;
hi = (hi + Math.imul(ah4, bh1)) | 0;
lo = (lo + Math.imul(al3, bl2)) | 0;
mid = (mid + Math.imul(al3, bh2)) | 0;
mid = (mid + Math.imul(ah3, bl2)) | 0;
hi = (hi + Math.imul(ah3, bh2)) | 0;
lo = (lo + Math.imul(al2, bl3)) | 0;
mid = (mid + Math.imul(al2, bh3)) | 0;
mid = (mid + Math.imul(ah2, bl3)) | 0;
hi = (hi + Math.imul(ah2, bh3)) | 0;
lo = (lo + Math.imul(al1, bl4)) | 0;
mid = (mid + Math.imul(al1, bh4)) | 0;
mid = (mid + Math.imul(ah1, bl4)) | 0;
hi = (hi + Math.imul(ah1, bh4)) | 0;
lo = (lo + Math.imul(al0, bl5)) | 0;
mid = (mid + Math.imul(al0, bh5)) | 0;
mid = (mid + Math.imul(ah0, bl5)) | 0;
hi = (hi + Math.imul(ah0, bh5)) | 0;
let w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
w5 &= 0x3ffffff;
/* k = 6 */
lo = Math.imul(al6, bl0);
mid = Math.imul(al6, bh0);
mid = (mid + Math.imul(ah6, bl0)) | 0;
hi = Math.imul(ah6, bh0);
lo = (lo + Math.imul(al5, bl1)) | 0;
mid = (mid + Math.imul(al5, bh1)) | 0;
mid = (mid + Math.imul(ah5, bl1)) | 0;
hi = (hi + Math.imul(ah5, bh1)) | 0;
lo = (lo + Math.imul(al4, bl2)) | 0;
mid = (mid + Math.imul(al4, bh2)) | 0;
mid = (mid + Math.imul(ah4, bl2)) | 0;
hi = (hi + Math.imul(ah4, bh2)) | 0;
lo = (lo + Math.imul(al3, bl3)) | 0;
mid = (mid + Math.imul(al3, bh3)) | 0;
mid = (mid + Math.imul(ah3, bl3)) | 0;
hi = (hi + Math.imul(ah3, bh3)) | 0;
lo = (lo + Math.imul(al2, bl4)) | 0;
mid = (mid + Math.imul(al2, bh4)) | 0;
mid = (mid + Math.imul(ah2, bl4)) | 0;
hi = (hi + Math.imul(ah2, bh4)) | 0;
lo = (lo + Math.imul(al1, bl5)) | 0;
mid = (mid + Math.imul(al1, bh5)) | 0;
mid = (mid + Math.imul(ah1, bl5)) | 0;
hi = (hi + Math.imul(ah1, bh5)) | 0;
lo = (lo + Math.imul(al0, bl6)) | 0;
mid = (mid + Math.imul(al0, bh6)) | 0;
mid = (mid + Math.imul(ah0, bl6)) | 0;
hi = (hi + Math.imul(ah0, bh6)) | 0;
let w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
w6 &= 0x3ffffff;
/* k = 7 */
lo = Math.imul(al7, bl0);
mid = Math.imul(al7, bh0);
mid = (mid + Math.imul(ah7, bl0)) | 0;
hi = Math.imul(ah7, bh0);
lo = (lo + Math.imul(al6, bl1)) | 0;
mid = (mid + Math.imul(al6, bh1)) | 0;
mid = (mid + Math.imul(ah6, bl1)) | 0;
hi = (hi + Math.imul(ah6, bh1)) | 0;
lo = (lo + Math.imul(al5, bl2)) | 0;
mid = (mid + Math.imul(al5, bh2)) | 0;
mid = (mid + Math.imul(ah5, bl2)) | 0;
hi = (hi + Math.imul(ah5, bh2)) | 0;
lo = (lo + Math.imul(al4, bl3)) | 0;
mid = (mid + Math.imul(al4, bh3)) | 0;
mid = (mid + Math.imul(ah4, bl3)) | 0;
hi = (hi + Math.imul(ah4, bh3)) | 0;
lo = (lo + Math.imul(al3, bl4)) | 0;
mid = (mid + Math.imul(al3, bh4)) | 0;
mid = (mid + Math.imul(ah3, bl4)) | 0;
hi = (hi + Math.imul(ah3, bh4)) | 0;
lo = (lo + Math.imul(al2, bl5)) | 0;
mid = (mid + Math.imul(al2, bh5)) | 0;
mid = (mid + Math.imul(ah2, bl5)) | 0;
hi = (hi + Math.imul(ah2, bh5)) | 0;
lo = (lo + Math.imul(al1, bl6)) | 0;
mid = (mid + Math.imul(al1, bh6)) | 0;
mid = (mid + Math.imul(ah1, bl6)) | 0;
hi = (hi + Math.imul(ah1, bh6)) | 0;
lo = (lo + Math.imul(al0, bl7)) | 0;
mid = (mid + Math.imul(al0, bh7)) | 0;
mid = (mid + Math.imul(ah0, bl7)) | 0;
hi = (hi + Math.imul(ah0, bh7)) | 0;
let w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
w7 &= 0x3ffffff;
/* k = 8 */
lo = Math.imul(al8, bl0);
mid = Math.imul(al8, bh0);
mid = (mid + Math.imul(ah8, bl0)) | 0;
hi = Math.imul(ah8, bh0);
lo = (lo + Math.imul(al7, bl1)) | 0;
mid = (mid + Math.imul(al7, bh1)) | 0;
mid = (mid + Math.imul(ah7, bl1)) | 0;
hi = (hi + Math.imul(ah7, bh1)) | 0;
lo = (lo + Math.imul(al6, bl2)) | 0;
mid = (mid + Math.imul(al6, bh2)) | 0;
mid = (mid + Math.imul(ah6, bl2)) | 0;
hi = (hi + Math.imul(ah6, bh2)) | 0;
lo = (lo + Math.imul(al5, bl3)) | 0;
mid = (mid + Math.imul(al5, bh3)) | 0;
mid = (mid + Math.imul(ah5, bl3)) | 0;
hi = (hi + Math.imul(ah5, bh3)) | 0;
lo = (lo + Math.imul(al4, bl4)) | 0;
mid = (mid + Math.imul(al4, bh4)) | 0;
mid = (mid + Math.imul(ah4, bl4)) | 0;
hi = (hi + Math.imul(ah4, bh4)) | 0;
lo = (lo + Math.imul(al3, bl5)) | 0;
mid = (mid + Math.imul(al3, bh5)) | 0;
mid = (mid + Math.imul(ah3, bl5)) | 0;
hi = (hi + Math.imul(ah3, bh5)) | 0;
lo = (lo + Math.imul(al2, bl6)) | 0;
mid = (mid + Math.imul(al2, bh6)) | 0;
mid = (mid + Math.imul(ah2, bl6)) | 0;
hi = (hi + Math.imul(ah2, bh6)) | 0;
lo = (lo + Math.imul(al1, bl7)) | 0;
mid = (mid + Math.imul(al1, bh7)) | 0;
mid = (mid + Math.imul(ah1, bl7)) | 0;
hi = (hi + Math.imul(ah1, bh7)) | 0;
lo = (lo + Math.imul(al0, bl8)) | 0;
mid = (mid + Math.imul(al0, bh8)) | 0;
mid = (mid + Math.imul(ah0, bl8)) | 0;
hi = (hi + Math.imul(ah0, bh8)) | 0;
let w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
w8 &= 0x3ffffff;
/* k = 9 */
lo = Math.imul(al9, bl0);
mid = Math.imul(al9, bh0);
mid = (mid + Math.imul(ah9, bl0)) | 0;
hi = Math.imul(ah9, bh0);
lo = (lo + Math.imul(al8, bl1)) | 0;
mid = (mid + Math.imul(al8, bh1)) | 0;
mid = (mid + Math.imul(ah8, bl1)) | 0;
hi = (hi + Math.imul(ah8, bh1)) | 0;
lo = (lo + Math.imul(al7, bl2)) | 0;
mid = (mid + Math.imul(al7, bh2)) | 0;
mid = (mid + Math.imul(ah7, bl2)) | 0;
hi = (hi + Math.imul(ah7, bh2)) | 0;
lo = (lo + Math.imul(al6, bl3)) | 0;
mid = (mid + Math.imul(al6, bh3)) | 0;
mid = (mid + Math.imul(ah6, bl3)) | 0;
hi = (hi + Math.imul(ah6, bh3)) | 0;
lo = (lo + Math.imul(al5, bl4)) | 0;
mid = (mid + Math.imul(al5, bh4)) | 0;
mid = (mid + Math.imul(ah5, bl4)) | 0;
hi = (hi + Math.imul(ah5, bh4)) | 0;
lo = (lo + Math.imul(al4, bl5)) | 0;
mid = (mid + Math.imul(al4, bh5)) | 0;
mid = (mid + Math.imul(ah4, bl5)) | 0;
hi = (hi + Math.imul(ah4, bh5)) | 0;
lo = (lo + Math.imul(al3, bl6)) | 0;
mid = (mid + Math.imul(al3, bh6)) | 0;
mid = (mid + Math.imul(ah3, bl6)) | 0;
hi = (hi + Math.imul(ah3, bh6)) | 0;
lo = (lo + Math.imul(al2, bl7)) | 0;
mid = (mid + Math.imul(al2, bh7)) | 0;
mid = (mid + Math.imul(ah2, bl7)) | 0;
hi = (hi + Math.imul(ah2, bh7)) | 0;
lo = (lo + Math.imul(al1, bl8)) | 0;
mid = (mid + Math.imul(al1, bh8)) | 0;
mid = (mid + Math.imul(ah1, bl8)) | 0;
hi = (hi + Math.imul(ah1, bh8)) | 0;
lo = (lo + Math.imul(al0, bl9)) | 0;
mid = (mid + Math.imul(al0, bh9)) | 0;
mid = (mid + Math.imul(ah0, bl9)) | 0;
hi = (hi + Math.imul(ah0, bh9)) | 0;
let w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
w9 &= 0x3ffffff;
/* k = 10 */
lo = Math.imul(al9, bl1);
mid = Math.imul(al9, bh1);
mid = (mid + Math.imul(ah9, bl1)) | 0;
hi = Math.imul(ah9, bh1);
lo = (lo + Math.imul(al8, bl2)) | 0;
mid = (mid + Math.imul(al8, bh2)) | 0;
mid = (mid + Math.imul(ah8, bl2)) | 0;
hi = (hi + Math.imul(ah8, bh2)) | 0;
lo = (lo + Math.imul(al7, bl3)) | 0;
mid = (mid + Math.imul(al7, bh3)) | 0;
mid = (mid + Math.imul(ah7, bl3)) | 0;
hi = (hi + Math.imul(ah7, bh3)) | 0;
lo = (lo + Math.imul(al6, bl4)) | 0;
mid = (mid + Math.imul(al6, bh4)) | 0;
mid = (mid + Math.imul(ah6, bl4)) | 0;
hi = (hi + Math.imul(ah6, bh4)) | 0;
lo = (lo + Math.imul(al5, bl5)) | 0;
mid = (mid + Math.imul(al5, bh5)) | 0;
mid = (mid + Math.imul(ah5, bl5)) | 0;
hi = (hi + Math.imul(ah5, bh5)) | 0;
lo = (lo + Math.imul(al4, bl6)) | 0;
mid = (mid + Math.imul(al4, bh6)) | 0;
mid = (mid + Math.imul(ah4, bl6)) | 0;
hi = (hi + Math.imul(ah4, bh6)) | 0;
lo = (lo + Math.imul(al3, bl7)) | 0;
mid = (mid + Math.imul(al3, bh7)) | 0;
mid = (mid + Math.imul(ah3, bl7)) | 0;
hi = (hi + Math.imul(ah3, bh7)) | 0;
lo = (lo + Math.imul(al2, bl8)) | 0;
mid = (mid + Math.imul(al2, bh8)) | 0;
mid = (mid + Math.imul(ah2, bl8)) | 0;
hi = (hi + Math.imul(ah2, bh8)) | 0;
lo = (lo + Math.imul(al1, bl9)) | 0;
mid = (mid + Math.imul(al1, bh9)) | 0;
mid = (mid + Math.imul(ah1, bl9)) | 0;
hi = (hi + Math.imul(ah1, bh9)) | 0;
let w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
w10 &= 0x3ffffff;
/* k = 11 */
lo = Math.imul(al9, bl2);
mid = Math.imul(al9, bh2);
mid = (mid + Math.imul(ah9, bl2)) | 0;
hi = Math.imul(ah9, bh2);
lo = (lo + Math.imul(al8, bl3)) | 0;
mid = (mid + Math.imul(al8, bh3)) | 0;
mid = (mid + Math.imul(ah8, bl3)) | 0;
hi = (hi + Math.imul(ah8, bh3)) | 0;
lo = (lo + Math.imul(al7, bl4)) | 0;
mid = (mid + Math.imul(al7, bh4)) | 0;
mid = (mid + Math.imul(ah7, bl4)) | 0;
hi = (hi + Math.imul(ah7, bh4)) | 0;
lo = (lo + Math.imul(al6, bl5)) | 0;
mid = (mid + Math.imul(al6, bh5)) | 0;
mid = (mid + Math.imul(ah6, bl5)) | 0;
hi = (hi + Math.imul(ah6, bh5)) | 0;
lo = (lo + Math.imul(al5, bl6)) | 0;
mid = (mid + Math.imul(al5, bh6)) | 0;
mid = (mid + Math.imul(ah5, bl6)) | 0;
hi = (hi + Math.imul(ah5, bh6)) | 0;
lo = (lo + Math.imul(al4, bl7)) | 0;
mid = (mid + Math.imul(al4, bh7)) | 0;
mid = (mid + Math.imul(ah4, bl7)) | 0;
hi = (hi + Math.imul(ah4, bh7)) | 0;
lo = (lo + Math.imul(al3, bl8)) | 0;
mid = (mid + Math.imul(al3, bh8)) | 0;
mid = (mid + Math.imul(ah3, bl8)) | 0;
hi = (hi + Math.imul(ah3, bh8)) | 0;
lo = (lo + Math.imul(al2, bl9)) | 0;
mid = (mid + Math.imul(al2, bh9)) | 0;
mid = (mid + Math.imul(ah2, bl9)) | 0;
hi = (hi + Math.imul(ah2, bh9)) | 0;
let w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
w11 &= 0x3ffffff;
/* k = 12 */
lo = Math.imul(al9, bl3);
mid = Math.imul(al9, bh3);
mid = (mid + Math.imul(ah9, bl3)) | 0;
hi = Math.imul(ah9, bh3);
lo = (lo + Math.imul(al8, bl4)) | 0;
mid = (mid + Math.imul(al8, bh4)) | 0;
mid = (mid + Math.imul(ah8, bl4)) | 0;
hi = (hi + Math.imul(ah8, bh4)) | 0;
lo = (lo + Math.imul(al7, bl5)) | 0;
mid = (mid + Math.imul(al7, bh5)) | 0;
mid = (mid + Math.imul(ah7, bl5)) | 0;
hi = (hi + Math.imul(ah7, bh5)) | 0;
lo = (lo + Math.imul(al6, bl6)) | 0;
mid = (mid + Math.imul(al6, bh6)) | 0;
mid = (mid + Math.imul(ah6, bl6)) | 0;
hi = (hi + Math.imul(ah6, bh6)) | 0;
lo = (lo + Math.imul(al5, bl7)) | 0;
mid = (mid + Math.imul(al5, bh7)) | 0;
mid = (mid + Math.imul(ah5, bl7)) | 0;
hi = (hi + Math.imul(ah5, bh7)) | 0;
lo = (lo + Math.imul(al4, bl8)) | 0;
mid = (mid + Math.imul(al4, bh8)) | 0;
mid = (mid + Math.imul(ah4, bl8)) | 0;
hi = (hi + Math.imul(ah4, bh8)) | 0;
lo = (lo + Math.imul(al3, bl9)) | 0;
mid = (mid + Math.imul(al3, bh9)) | 0;
mid = (mid + Math.imul(ah3, bl9)) | 0;
hi = (hi + Math.imul(ah3, bh9)) | 0;
let w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
w12 &= 0x3ffffff;
/* k = 13 */
lo = Math.imul(al9, bl4);
mid = Math.imul(al9, bh4);
mid = (mid + Math.imul(ah9, bl4)) | 0;
hi = Math.imul(ah9, bh4);
lo = (lo + Math.imul(al8, bl5)) | 0;
mid = (mid + Math.imul(al8, bh5)) | 0;
mid = (mid + Math.imul(ah8, bl5)) | 0;
hi = (hi + Math.imul(ah8, bh5)) | 0;
lo = (lo + Math.imul(al7, bl6)) | 0;
mid = (mid + Math.imul(al7, bh6)) | 0;
mid = (mid + Math.imul(ah7, bl6)) | 0;
hi = (hi + Math.imul(ah7, bh6)) | 0;
lo = (lo + Math.imul(al6, bl7)) | 0;
mid = (mid + Math.imul(al6, bh7)) | 0;
mid = (mid + Math.imul(ah6, bl7)) | 0;
hi = (hi + Math.imul(ah6, bh7)) | 0;
lo = (lo + Math.imul(al5, bl8)) | 0;
mid = (mid + Math.imul(al5, bh8)) | 0;
mid = (mid + Math.imul(ah5, bl8)) | 0;
hi = (hi + Math.imul(ah5, bh8)) | 0;
lo = (lo + Math.imul(al4, bl9)) | 0;
mid = (mid + Math.imul(al4, bh9)) | 0;
mid = (mid + Math.imul(ah4, bl9)) | 0;
hi = (hi + Math.imul(ah4, bh9)) | 0;
let w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
w13 &= 0x3ffffff;
/* k = 14 */
lo = Math.imul(al9, bl5);
mid = Math.imul(al9, bh5);
mid = (mid + Math.imul(ah9, bl5)) | 0;
hi = Math.imul(ah9, bh5);
lo = (lo + Math.imul(al8, bl6)) | 0;
mid = (mid + Math.imul(al8, bh6)) | 0;
mid = (mid + Math.imul(ah8, bl6)) | 0;
hi = (hi + Math.imul(ah8, bh6)) | 0;
lo = (lo + Math.imul(al7, bl7)) | 0;
mid = (mid + Math.imul(al7, bh7)) | 0;
mid = (mid + Math.imul(ah7, bl7)) | 0;
hi = (hi + Math.imul(ah7, bh7)) | 0;
lo = (lo + Math.imul(al6, bl8)) | 0;
mid = (mid + Math.imul(al6, bh8)) | 0;
mid = (mid + Math.imul(ah6, bl8)) | 0;
hi = (hi + Math.imul(ah6, bh8)) | 0;
lo = (lo + Math.imul(al5, bl9)) | 0;
mid = (mid + Math.imul(al5, bh9)) | 0;
mid = (mid + Math.imul(ah5, bl9)) | 0;
hi = (hi + Math.imul(ah5, bh9)) | 0;
let w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
w14 &= 0x3ffffff;
/* k = 15 */
lo = Math.imul(al9, bl6);
mid = Math.imul(al9, bh6);
mid = (mid + Math.imul(ah9, bl6)) | 0;
hi = Math.imul(ah9, bh6);
lo = (lo + Math.imul(al8, bl7)) | 0;
mid = (mid + Math.imul(al8, bh7)) | 0;
mid = (mid + Math.imul(ah8, bl7)) | 0;
hi = (hi + Math.imul(ah8, bh7)) | 0;
lo = (lo + Math.imul(al7, bl8)) | 0;
mid = (mid + Math.imul(al7, bh8)) | 0;
mid = (mid + Math.imul(ah7, bl8)) | 0;
hi = (hi + Math.imul(ah7, bh8)) | 0;
lo = (lo + Math.imul(al6, bl9)) | 0;
mid = (mid + Math.imul(al6, bh9)) | 0;
mid = (mid + Math.imul(ah6, bl9)) | 0;
hi = (hi + Math.imul(ah6, bh9)) | 0;
let w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
w15 &= 0x3ffffff;
/* k = 16 */
lo = Math.imul(al9, bl7);
mid = Math.imul(al9, bh7);
mid = (mid + Math.imul(ah9, bl7)) | 0;
hi = Math.imul(ah9, bh7);
lo = (lo + Math.imul(al8, bl8)) | 0;
mid = (mid + Math.imul(al8, bh8)) | 0;
mid = (mid + Math.imul(ah8, bl8)) | 0;
hi = (hi + Math.imul(ah8, bh8)) | 0;
lo = (lo + Math.imul(al7, bl9)) | 0;
mid = (mid + Math.imul(al7, bh9)) | 0;
mid = (mid + Math.imul(ah7, bl9)) | 0;
hi = (hi + Math.imul(ah7, bh9)) | 0;
let w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
w16 &= 0x3ffffff;
/* k = 17 */
lo = Math.imul(al9, bl8);
mid = Math.imul(al9, bh8);
mid = (mid + Math.imul(ah9, bl8)) | 0;
hi = Math.imul(ah9, bh8);
lo = (lo + Math.imul(al8, bl9)) | 0;
mid = (mid + Math.imul(al8, bh9)) | 0;
mid = (mid + Math.imul(ah8, bl9)) | 0;
hi = (hi + Math.imul(ah8, bh9)) | 0;
let w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
w17 &= 0x3ffffff;
/* k = 18 */
lo = Math.imul(al9, bl9);
mid = Math.imul(al9, bh9);
mid = (mid + Math.imul(ah9, bl9)) | 0;
hi = Math.imul(ah9, bh9);
let w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
w18 &= 0x3ffffff;
o[0] = w0;
o[1] = w1;
o[2] = w2;
o[3] = w3;
o[4] = w4;
o[5] = w5;
o[6] = w6;
o[7] = w7;
o[8] = w8;
o[9] = w9;
o[10] = w10;
o[11] = w11;
o[12] = w12;
o[13] = w13;
o[14] = w14;
o[15] = w15;
o[16] = w16;
o[17] = w17;
o[18] = w18;
if (c !== 0) {
o[19] = c;
out.length += 1;
}
// Note: we shouldn't need to strip here.
return out;
}
// Polyfill comb.
if (!Math.imul)
comb10MulTo = smallMulTo;
/*
* Expose
*/
BN.Red = Red;
module.exports = BN;
}],
[/* 33 */ 'bcrypto', '/lib/internal/custom-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* custom.js - custom inspect symbol for bcrypto
* Copyright (c) 2018-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
exports.custom = 'inspect';
}],
[/* 34 */ 'bcrypto', '/lib/internal/asn1.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* asn1.js - asn1 parsing for bcrypto
* Copyright (c) 2020, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
const assert = require('assert');
const BN = __node_require__(31 /* '../bn' */);
/*
* ASN1
*/
function readSize(data, pos, strict) {
assert(Buffer.isBuffer(data));
assert((pos >>> 0) === pos);
assert(typeof strict === 'boolean');
if (pos >= data.length)
throw new Error('Invalid size.');
const field = data[pos];
const bytes = field & 0x7f;
pos += 1;
// Definite form.
if ((field & 0x80) === 0) {
// Short form.
return [bytes, pos];
}
// Indefinite form.
if (strict && bytes === 0)
throw new Error('Indefinite length.');
// Long form.
let size = 0;
for (let i = 0; i < bytes; i++) {
assert(pos < data.length);
const ch = data[pos];
pos += 1;
if (size >= (1 << 24))
throw new Error('Length too large.');
size *= 0x100;
size += ch;
if (strict && size === 0)
throw new Error('Unexpected leading zeroes.');
}
if (strict && size < 0x80)
throw new Error('Non-minimal length.');
return [size, pos];
}
function readSeq(data, pos, strict = true) {
assert(Buffer.isBuffer(data));
assert((pos >>> 0) === pos);
assert(typeof strict === 'boolean');
if (pos >= data.length || data[pos] !== 0x30)
throw new Error('Invalid sequence tag.');
pos += 1;
let size;
[size, pos] = readSize(data, pos, strict);
if (strict && pos + size !== data.length)
throw new Error('Trailing bytes.');
return pos;
}
function readInt(data, pos, strict = true) {
assert(Buffer.isBuffer(data));
assert((pos >>> 0) === pos);
assert(typeof strict === 'boolean');
if (pos >= data.length || data[pos] !== 0x02)
throw new Error('Invalid integer tag.');
pos += 1;
let size;
[size, pos] = readSize(data, pos, strict);
if (pos + size > data.length)
throw new Error('Integer body out of bounds.');
if (strict) {
// Zero length integer.
if (size === 0)
throw new Error('Zero length integer.');
// No negatives.
if (data[pos] & 0x80)
throw new Error('Integers must be positive.');
// Allow zero only if it prefixes a high bit.
if (size > 1) {
if (data[pos] === 0x00 && (data[pos + 1] & 0x80) === 0x00)
throw new Error('Unexpected leading zeroes.');
}
}
// Eat leading zeroes.
while (size > 0 && data[pos] === 0x00) {
pos += 1;
size -= 1;
}
// No reason to have an integer larger than this.
if (size > 2048)
throw new Error('Invalid integer size.');
const num = BN.decode(data.slice(pos, pos + size));
pos += size;
return [num, pos];
}
function readVersion(data, pos, version, strict = true) {
assert(Buffer.isBuffer(data));
assert((pos >>> 0) === pos);
assert((version & 0xff) === version);
assert(typeof strict === 'boolean');
let num;
[num, pos] = readInt(data, pos, strict);
if (num.cmpn(version) !== 0)
throw new Error('Invalid version.');
return pos;
}
function sizeSize(size) {
assert((size >>> 0) === size);
if (size <= 0x7f) // [size]
return 1;
if (size <= 0xff) // 0x81 [size]
return 2;
assert(size <= 0xffff);
return 3; // 0x82 [size-hi] [size-lo]
}
function sizeSeq(size) {
return 1 + sizeSize(size) + size;
}
function sizeInt(num) {
assert(num instanceof BN);
// 0x02 [size] [0x00?] [int]
const bits = num.bitLength();
let size = (bits + 7) >>> 3;
if (bits > 0 && (bits & 7) === 0)
size += num.testn(bits - 1);
if (bits === 0)
size = 1;
return 1 + sizeSize(size) + size;
}
function sizeVersion(version) {
assert((version & 0xff) === version);
return 3;
}
function writeSize(data, pos, size) {
assert(Buffer.isBuffer(data));
assert((pos >>> 0) === pos);
assert((size >>> 0) === size);
if (size <= 0x7f) {
// [size]
data[pos++] = size;
} else if (size <= 0xff) {
// 0x81 [size]
data[pos++] = 0x81;
data[pos++] = size;
} else {
// 0x82 [size-hi] [size-lo]
assert(size <= 0xffff);
data[pos++] = 0x82;
data[pos++] = size >> 8;
data[pos++] = size & 0xff;
}
assert(pos <= data.length);
return pos;
}
function writeSeq(data, pos, size) {
assert(Buffer.isBuffer(data));
assert((pos >>> 0) === pos);
data[pos++] = 0x30;
return writeSize(data, pos, size);
}
function writeInt(data, pos, num) {
assert(Buffer.isBuffer(data));
assert((pos >>> 0) === pos);
assert(num instanceof BN);
// 0x02 [size] [0x00?] [int]
const bits = num.bitLength();
let size = (bits + 7) >>> 3;
let pad = 0;
if (bits > 0 && (bits & 7) === 0)
pad = num.testn(bits - 1);
if (bits === 0)
size = 1;
data[pos++] = 0x02;
pos = writeSize(data, pos, pad + size);
if (pad)
data[pos++] = 0x00;
if (bits !== 0)
num.encode().copy(data, pos);
else
data[pos] = 0x00;
pos += size;
assert(pos <= data.length);
return pos;
}
function writeVersion(data, pos, version) {
assert(Buffer.isBuffer(data));
assert((pos >>> 0) === pos);
assert((version & 0xff) === version);
assert(pos + 3 <= data.length);
data[pos++] = 0x02;
data[pos++] = 0x01;
data[pos++] = version;
return pos;
}
/*
* Expose
*/
exports.readSize = readSize;
exports.readSeq = readSeq;
exports.readInt = readInt;
exports.readVersion = readVersion;
exports.sizeSize = sizeSize;
exports.sizeSeq = sizeSeq;
exports.sizeInt = sizeInt;
exports.sizeVersion = sizeVersion;
exports.writeSize = writeSize;
exports.writeSeq = writeSeq;
exports.writeInt = writeInt;
exports.writeVersion = writeVersion;
}],
[/* 35 */ 'bcrypto', '/lib/js/schnorr-legacy.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* schnorr-legacy.js - bip-schnorr for bcrypto
* Copyright (c) 2019-2020, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on sipa/bip-schnorr:
* Copyright (c) 2018-2019, Pieter Wuille (2-clause BSD License).
* https://github.com/sipa/bips/blob/d194620/bip-schnorr/reference.py
*
* Parts of this software are based on ElementsProject/secp256k1-zkp:
* Copyright (c) 2013, Pieter Wuille.
* https://github.com/ElementsProject/secp256k1-zkp
*
* Resources:
* https://github.com/sipa/bips/blob/d194620/bip-schnorr.mediawiki
* https://github.com/sipa/bips/blob/d194620/bip-schnorr/reference.py
* https://github.com/sipa/bips/blob/d194620/bip-schnorr/test-vectors.csv
* https://github.com/ElementsProject/secp256k1-zkp/tree/11af701/src/modules/schnorrsig
* https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-05-15-schnorr.md
*
* References:
*
* [SCHNORR] Schnorr Signatures for secp256k1
* Pieter Wuille
* https://github.com/sipa/bips/blob/d194620/bip-schnorr.mediawiki
*
* [CASH] Schnorr Signature specification
* Mark B. Lundeberg
* https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-05-15-schnorr.md
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const BatchRNG = __node_require__(36 /* './batch-rng' */);
const BN = __node_require__(31 /* '../bn' */);
/**
* Schnorr
*/
class Schnorr {
constructor(curve, hash) {
this.curve = curve;
this.hash = hash;
this.rng = new BatchRNG(this.curve, this.encode.bind(this));
}
check() {
// [SCHNORR] "Footnotes".
// Must be congruent to 3 mod 4.
if (this.curve.p.andln(3) !== 3)
throw new Error(`Schnorr is not supported for ${this.curve.id}.`);
}
encode(key) {
// Extra speedy key reserialization.
assert(Buffer.isBuffer(key));
const {fieldSize} = this.curve;
if (key.length === 1 + fieldSize)
return key;
if (key.length !== 1 + fieldSize * 2)
throw new Error('Invalid point.');
const out = Buffer.alloc(1 + fieldSize);
out[0] = 0x02 | (key[key.length - 1] & 1);
key.copy(out, 1, 1, 1 + fieldSize);
return out;
}
hashInt(...items) {
// [SCHNORR] "Specification".
// eslint-disable-next-line
const h = new this.hash();
h.init();
for (const item of items)
h.update(item);
let hash = h.final(this.curve.scalarSize);
if (hash.length > this.curve.scalarSize)
hash = hash.slice(0, this.curve.scalarSize);
const num = BN.decode(hash, this.curve.endian);
num.iumaskn(this.curve.scalarBits);
return num.imod(this.curve.n);
}
hashNonce(a, m) {
return this.hashInt(a, m);
}
hashChallenge(R, A, m) {
return this.hashInt(R, this.encode(A), m);
}
sign(msg, key) {
assert(Buffer.isBuffer(msg));
this.check();
return this._sign(msg, key);
}
_sign(msg, key) {
// Schnorr Signing.
//
// [SCHNORR] "Signing".
// [CASH] "Recommended practices for secure signature generation".
//
// Assumptions:
//
// - Let `H` be a cryptographic hash function.
// - Let `m` be a 32-byte array.
// - Let `a` be a secret non-zero scalar.
// - k != 0.
//
// Computation:
//
// A = G * a
// k = H(a, m) mod n
// R = G * k
// k = -k mod n, if y(R) is not square
// r = x(R)
// e = H(r, A, m) mod n
// s = (k + e * a) mod n
// S = (r, s)
//
// Note that `k` must remain secret,
// otherwise an attacker can compute:
//
// a = (s - k) / e mod n
const {n} = this.curve;
const G = this.curve.g;
const a = this.curve.decodeScalar(key);
if (a.isZero() || a.cmp(n) >= 0)
throw new Error('Invalid private key.');
const A = G.mulBlind(a);
const k = this.hashNonce(key, msg);
if (k.isZero())
throw new Error('Signing failed (k\' = 0).');
const R = G.mulBlind(k);
if (!R.isSquare())
k.ineg().imod(n);
const Rraw = R.encodeX();
const Araw = A.encode();
const e = this.hashChallenge(Rraw, Araw, msg);
const s = k.add(e.mul(a)).imod(n);
return Buffer.concat([Rraw, this.curve.encodeScalar(s)]);
}
verify(msg, sig, key) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
this.check();
if (sig.length !== this.curve.fieldSize + this.curve.scalarSize)
return false;
try {
return this._verify(msg, sig, key);
} catch (e) {
return false;
}
}
_verify(msg, sig, key) {
// Schnorr Verification.
//
// [SCHNORR] "Verification".
// [CASH] "Signature verification algorithm".
//
// Assumptions:
//
// - Let `H` be a cryptographic hash function.
// - Let `m` be a 32-byte array.
// - Let `r` and `s` be signature elements.
// - Let `A` be a valid group element.
// - r^3 + a * r + b is square in F(p).
// - sqrt(r^3 + a * r + b) is square in F(p).
// - r < p, s < n.
// - R != O.
//
// Computation:
//
// R = (r, sqrt(r^3 + a * r + b))
// e = H(r, A, m) mod n
// R == G * s - A * e
//
// We can skip a square root with:
//
// e = H(r, A, m) mod n
// R = G * s - A * e
// y(R) is square
// x(R) == r
//
// We can also avoid affinization by
// replacing the two assertions with:
//
// (y(R) * z(R) mod p) is square
// x(R) == r * z(R)^2 mod p
//
// Furthermore, squareness can be calculated
// with a variable time Jacobi symbol algorithm.
const {p, n} = this.curve;
const G = this.curve.g;
const Rraw = sig.slice(0, this.curve.fieldSize);
const sraw = sig.slice(this.curve.fieldSize);
const r = this.curve.decodeField(Rraw);
const s = this.curve.decodeScalar(sraw);
const A = this.curve.decodePoint(key);
if (r.cmp(p) >= 0 || s.cmp(n) >= 0)
return false;
const e = this.hashChallenge(Rraw, key, msg);
const R = G.jmulAdd(s, A, e.ineg().imod(n));
if (!R.isSquare())
return false;
if (!R.eqX(r))
return false;
return true;
}
verifyBatch(batch) {
assert(Array.isArray(batch));
this.check();
for (const item of batch) {
assert(Array.isArray(item) && item.length === 3);
const [msg, sig, key] = item;
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
if (sig.length !== this.curve.fieldSize + this.curve.scalarSize)
return false;
}
try {
return this._verifyBatch(batch);
} catch (e) {
return false;
}
}
_verifyBatch(batch) {
// Schnorr Batch Verification.
//
// [SCHNORR] "Batch Verification".
//
// Assumptions:
//
// - Let `H` be a cryptographic hash function.
// - Let `m` be a 32-byte array.
// - Let `r` and `s` be signature elements.
// - Let `A` be a valid group element.
// - Let `i` be the batch item index.
// - r^3 + a * r + b is square in F(p).
// - sqrt(r^3 + a * r + b) is square in F(p).
// - r < p, s < n.
// - a1 = 1 mod n.
//
// Computation:
//
// Ri = (ri, sqrt(ri^3 + a * ri + b))
// ei = H(ri, Ai, mi) mod n
// ai = random integer in [1,n-1]
// lhs = si * ai + ... mod n
// rhs = Ri * ai + Ai * (ei * ai mod n) + ...
// G * -lhs + rhs == O
const {n} = this.curve;
const G = this.curve.g;
const points = new Array(1 + batch.length * 2);
const coeffs = new Array(1 + batch.length * 2);
const sum = new BN(0);
this.rng.init(batch);
points[0] = G;
coeffs[0] = sum;
for (let i = 0; i < batch.length; i++) {
const [msg, sig, key] = batch[i];
const Rraw = sig.slice(0, this.curve.fieldSize);
const sraw = sig.slice(this.curve.fieldSize);
const R = this.curve.decodeSquare(Rraw);
const s = this.curve.decodeScalar(sraw);
const A = this.curve.decodePoint(key);
if (s.cmp(n) >= 0)
return false;
const e = this.hashChallenge(Rraw, key, msg);
const a = this.rng.generate(i);
const ea = e.mul(a).imod(n);
sum.iadd(s.mul(a)).imod(n);
points[1 + i * 2 + 0] = R;
coeffs[1 + i * 2 + 0] = a;
points[1 + i * 2 + 1] = A;
coeffs[1 + i * 2 + 1] = ea;
}
sum.ineg().imod(n);
return this.curve.jmulAll(points, coeffs).isInfinity();
}
}
/*
* Expose
*/
module.exports = Schnorr;
}],
[/* 36 */ 'bcrypto', '/lib/js/batch-rng.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* batch-rng.js - batch rng for bcrypto
* Copyright (c) 2019-2020, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on ElementsProject/secp256k1-zkp:
* Copyright (c) 2013, Pieter Wuille.
* https://github.com/ElementsProject/secp256k1-zkp
*
* Resources:
* https://github.com/ElementsProject/secp256k1-zkp/blob/11af701/src/modules/schnorrsig/main_impl.h#L166
* https://github.com/ElementsProject/secp256k1-zkp/blob/11af701/src/scalar_4x64_impl.h#L972
* https://github.com/ElementsProject/secp256k1-zkp/blob/11af701/src/scalar_8x32_impl.h#L747
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const BN = __node_require__(31 /* '../bn' */);
const ChaCha20 = __node_require__(37 /* '../chacha20' */);
const SHA256 = __node_require__(39 /* '../sha256' */);
/**
* BatchRNG
*/
class BatchRNG {
constructor(curve, encode = key => key) {
this.curve = curve;
this.encode = encode;
this.hash = new SHA256();
this.chacha = new ChaCha20();
this.key = Buffer.alloc(32, 0x00);
this.iv = Buffer.alloc(8, 0x00);
this.cache = [new BN(1), new BN(1)];
}
init(batch) {
assert(Array.isArray(batch));
this.hash.init();
for (const [msg, sig, key] of batch) {
this.hash.update(SHA256.digest(msg));
this.hash.update(sig);
this.hash.update(this.encode(key));
}
this.key = this.hash.final();
this.cache[0] = new BN(1);
this.cache[1] = new BN(1);
return this;
}
encrypt(counter) {
const size = this.curve.scalarSize * 2;
const data = Buffer.alloc(size, 0x00);
const left = data.slice(0, this.curve.scalarSize);
const right = data.slice(this.curve.scalarSize);
this.chacha.init(this.key, this.iv, counter);
this.chacha.encrypt(data);
return [
this.curve.decodeScalar(left),
this.curve.decodeScalar(right)
];
}
refresh(counter) {
let overflow = 0;
for (;;) {
// First word is always zero.
this.iv[4] = overflow;
this.iv[5] = overflow >>> 8;
this.iv[6] = overflow >>> 16;
this.iv[7] = overflow >>> 24;
overflow += 1;
const [s1, s2] = this.encrypt(counter);
if (s1.isZero() || s1.cmp(this.curve.n) >= 0)
continue;
if (s2.isZero() || s2.cmp(this.curve.n) >= 0)
continue;
this.cache[0] = s1;
this.cache[1] = s2;
break;
}
}
generate(index) {
assert((index >>> 0) === index);
if (index & 1)
this.refresh(index >>> 1);
return this.cache[index & 1];
}
}
/*
* Expose
*/
module.exports = BatchRNG;
}],
[/* 37 */ 'bcrypto', '/lib/chacha20-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* chacha20.js - chacha20 for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(38 /* './js/chacha20' */);
}],
[/* 38 */ 'bcrypto', '/lib/js/chacha20.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* chacha20.js - chacha20 for bcrypto
* Copyright (c) 2016-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Resources
* https://en.wikipedia.org/wiki/Chacha20
* https://tools.ietf.org/html/rfc7539#section-2
* https://cr.yp.to/chacha.html
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
/*
* Constants
*/
const BIG_ENDIAN = new Int8Array(new Int16Array([1]).buffer)[0] === 0;
/**
* ChaCha20
*/
class ChaCha20 {
/**
* Create a ChaCha20 context.
* @constructor
*/
constructor() {
this.state = new Uint32Array(16);
this.stream = new Uint32Array(16);
this.bytes = new Uint8Array(this.stream.buffer);
this.pos = -1;
if (BIG_ENDIAN)
this.bytes = Buffer.alloc(64);
}
/**
* Initialize chacha20 with a key, nonce, and counter.
* @param {Buffer} key
* @param {Buffer} nonce
* @param {Number} counter
*/
init(key, nonce, counter) {
if (counter == null)
counter = 0;
assert(Buffer.isBuffer(key));
assert(Buffer.isBuffer(nonce));
assert(Number.isSafeInteger(counter));
if (key.length !== 16 && key.length !== 32)
throw new RangeError('Invalid key size.');
if (nonce.length >= 24) {
key = ChaCha20.derive(key, nonce.slice(0, 16));
nonce = nonce.slice(16);
}
this.state[0] = 0x61707865;
this.state[1] = key.length < 32 ? 0x3120646e : 0x3320646e;
this.state[2] = key.length < 32 ? 0x79622d36 : 0x79622d32;
this.state[3] = 0x6b206574;
this.state[4] = readU32(key, 0);
this.state[5] = readU32(key, 4);
this.state[6] = readU32(key, 8);
this.state[7] = readU32(key, 12);
this.state[8] = readU32(key, 16 % key.length);
this.state[9] = readU32(key, 20 % key.length);
this.state[10] = readU32(key, 24 % key.length);
this.state[11] = readU32(key, 28 % key.length);
this.state[12] = counter >>> 0;
if (nonce.length === 8) {
this.state[13] = (counter / 0x100000000) >>> 0;
this.state[14] = readU32(nonce, 0);
this.state[15] = readU32(nonce, 4);
} else if (nonce.length === 12) {
this.state[13] = readU32(nonce, 0);
this.state[14] = readU32(nonce, 4);
this.state[15] = readU32(nonce, 8);
} else if (nonce.length === 16) {
this.state[12] = readU32(nonce, 0);
this.state[13] = readU32(nonce, 4);
this.state[14] = readU32(nonce, 8);
this.state[15] = readU32(nonce, 12);
} else {
throw new RangeError('Invalid nonce size.');
}
this.pos = 0;
return this;
}
/**
* Encrypt/decrypt data.
* @param {Buffer} data - Will be mutated.
* @returns {Buffer}
*/
encrypt(data) {
assert(Buffer.isBuffer(data));
if (this.pos === -1)
throw new Error('Context is not initialized.');
for (let i = 0; i < data.length; i++) {
if ((this.pos & 63) === 0) {
this._block();
this.pos = 0;
}
data[i] ^= this.bytes[this.pos++];
}
return data;
}
/**
* Stir the stream.
*/
_block() {
for (let i = 0; i < 16; i++)
this.stream[i] = this.state[i];
for (let i = 0; i < 10; i++) {
qround(this.stream, 0, 4, 8, 12);
qround(this.stream, 1, 5, 9, 13);
qround(this.stream, 2, 6, 10, 14);
qround(this.stream, 3, 7, 11, 15);
qround(this.stream, 0, 5, 10, 15);
qround(this.stream, 1, 6, 11, 12);
qround(this.stream, 2, 7, 8, 13);
qround(this.stream, 3, 4, 9, 14);
}
for (let i = 0; i < 16; i++)
this.stream[i] += this.state[i];
if (BIG_ENDIAN) {
for (let i = 0; i < 16; i++)
writeU32(this.bytes, this.stream[i], i * 4);
}
this.state[12] += 1;
if (this.state[12] === 0)
this.state[13] += 1;
}
/**
* Destroy context.
*/
destroy() {
for (let i = 0; i < 16; i++) {
this.state[i] = 0;
this.stream[i] = 0;
}
if (BIG_ENDIAN) {
for (let i = 0; i < 64; i++)
this.bytes[i] = 0;
}
this.pos = -1;
return this;
}
/**
* Derive key with XChaCha20.
* @param {Buffer} key
* @param {Buffer} nonce
* @returns {Buffer}
*/
static derive(key, nonce) {
assert(Buffer.isBuffer(key));
assert(Buffer.isBuffer(nonce));
if (key.length !== 16 && key.length !== 32)
throw new RangeError('Invalid key size.');
if (nonce.length !== 16)
throw new RangeError('Invalid nonce size.');
const state = new Uint32Array(16);
state[0] = 0x61707865;
state[1] = key.length < 32 ? 0x3120646e : 0x3320646e;
state[2] = key.length < 32 ? 0x79622d36 : 0x79622d32;
state[3] = 0x6b206574;
state[4] = readU32(key, 0);
state[5] = readU32(key, 4);
state[6] = readU32(key, 8);
state[7] = readU32(key, 12);
state[8] = readU32(key, 16 % key.length);
state[9] = readU32(key, 20 % key.length);
state[10] = readU32(key, 24 % key.length);
state[11] = readU32(key, 28 % key.length);
state[12] = readU32(nonce, 0);
state[13] = readU32(nonce, 4);
state[14] = readU32(nonce, 8);
state[15] = readU32(nonce, 12);
for (let i = 0; i < 10; i++) {
qround(state, 0, 4, 8, 12);
qround(state, 1, 5, 9, 13);
qround(state, 2, 6, 10, 14);
qround(state, 3, 7, 11, 15);
qround(state, 0, 5, 10, 15);
qround(state, 1, 6, 11, 12);
qround(state, 2, 7, 8, 13);
qround(state, 3, 4, 9, 14);
}
const out = Buffer.alloc(32);
writeU32(out, state[0], 0);
writeU32(out, state[1], 4);
writeU32(out, state[2], 8);
writeU32(out, state[3], 12);
writeU32(out, state[12], 16);
writeU32(out, state[13], 20);
writeU32(out, state[14], 24);
writeU32(out, state[15], 28);
return out;
}
}
/*
* Static
*/
ChaCha20.native = 0;
/*
* Helpers
*/
function qround(x, a, b, c, d) {
x[a] += x[b];
x[d] = rotl32(x[d] ^ x[a], 16);
x[c] += x[d];
x[b] = rotl32(x[b] ^ x[c], 12);
x[a] += x[b];
x[d] = rotl32(x[d] ^ x[a], 8);
x[c] += x[d];
x[b] = rotl32(x[b] ^ x[c], 7);
}
function rotl32(w, b) {
return (w << b) | (w >>> (32 - b));
}
function readU32(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off] * 0x1000000);
}
function writeU32(dst, num, off) {
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
num >>>= 8;
dst[off++] = num;
return off;
}
/*
* Expose
*/
module.exports = ChaCha20;
}],
[/* 39 */ 'bcrypto', '/lib/sha256-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* sha256.js - sha256 for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(20 /* './js/sha256' */);
}],
[/* 40 */ 'bcrypto', '/lib/hmac-drbg-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* hmac-drbg.js - hmac-drbg for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(41 /* './js/hmac-drbg' */);
}],
[/* 41 */ 'bcrypto', '/lib/js/hmac-drbg.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* hmac-drbg.js - hmac-drbg implementation for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on indutny/hmac-drbg:
* Copyright Fedor Indutny, 2017.
* https://github.com/indutny/hmac-drbg
*
* Resources:
* https://tools.ietf.org/html/rfc6979
* https://csrc.nist.gov/publications/detail/sp/800-90a/archive/2012-01-23
* https://github.com/indutny/hmac-drbg/blob/master/lib/hmac-drbg.js
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
/*
* Constants
*/
const RESEED_INTERVAL = 0x1000000000000;
const ZERO = Buffer.from([0x00]);
const ONE = Buffer.from([0x01]);
/**
* HmacDRBG
*/
class HmacDRBG {
constructor(hash, entropy, nonce, pers) {
assert(hash && typeof hash.id === 'string');
this.hash = hash;
this.minEntropy = hash.id === 'SHA1' ? 10 : 24;
this.K = Buffer.alloc(hash.size);
this.V = Buffer.alloc(hash.size);
this.rounds = 0;
if (entropy)
this.init(entropy, nonce, pers);
}
init(entropy, nonce, pers) {
if (nonce == null)
nonce = Buffer.alloc(0);
if (pers == null)
pers = Buffer.alloc(0);
assert(Buffer.isBuffer(entropy));
assert(Buffer.isBuffer(nonce));
assert(Buffer.isBuffer(pers));
for (let i = 0; i < this.V.length; i++) {
this.K[i] = 0x00;
this.V[i] = 0x01;
}
const seed = Buffer.concat([entropy, nonce, pers]);
if (seed.length < this.minEntropy)
throw new Error('Not enough entropy.');
this.update(seed);
this.rounds = 1;
return this;
}
reseed(entropy, add) {
if (add == null)
add = Buffer.alloc(0);
assert(Buffer.isBuffer(entropy));
assert(Buffer.isBuffer(add));
if (this.rounds === 0)
throw new Error('DRBG not initialized.');
const seed = Buffer.concat([entropy, add]);
if (seed.length < this.minEntropy)
throw new Error('Not enough entropy.');
this.update(seed);
this.rounds = 1;
return this;
}
generate(len, add) {
assert((len >>> 0) === len);
assert(add == null || Buffer.isBuffer(add));
if (this.rounds === 0)
throw new Error('DRBG not initialized.');
if (this.rounds > RESEED_INTERVAL)
throw new Error('Reseed is required.');
if (add && add.length > 0)
this.update(add);
const blocks = Math.ceil(len / this.hash.size);
const out = Buffer.alloc(blocks * this.hash.size);
for (let i = 0; i < blocks; i++) {
this.V = this.mac(this.V);
this.V.copy(out, i * this.hash.size);
}
this.update(add);
this.rounds += 1;
return out.slice(0, len);
}
randomBytes(size) {
return this.generate(size);
}
/*
* Helpers
*/
mac(data) {
return this.hash.mac(data, this.K);
}
hmac() {
return this.hash.hmac().init(this.K);
}
update(seed) {
assert(seed == null || Buffer.isBuffer(seed));
const kmac = this.hmac();
kmac.update(this.V);
kmac.update(ZERO);
if (seed)
kmac.update(seed);
this.K = kmac.final();
this.V = this.mac(this.V);
if (seed && seed.length > 0) {
const kmac = this.hmac();
kmac.update(this.V);
kmac.update(ONE);
kmac.update(seed);
this.K = kmac.final();
this.V = this.mac(this.V);
}
return this;
}
}
/*
* Static
*/
HmacDRBG.native = 0;
/*
* Expose
*/
module.exports = HmacDRBG;
}],
[/* 42 */ 'bcrypto', '/lib/js/elliptic.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* elliptic.js - elliptic curves for bcrypto
* Copyright (c) 2018-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on indutny/elliptic:
* Copyright (c) 2014, Fedor Indutny (MIT License).
* https://github.com/indutny/elliptic
*
* Formulas from DJB and Tanja Lange [EFD].
*
* References:
*
* [GECC] Guide to Elliptic Curve Cryptography
* D. Hankerson, A. Menezes, and S. Vanstone
* https://tinyurl.com/guide-to-ecc
*
* [GLV] Faster Point Multiplication on Elliptic Curves
* R. Gallant, R. Lambert, and S. Vanstone
* https://link.springer.com/content/pdf/10.1007/3-540-44647-8_11.pdf
*
* [MONT1] Montgomery curves and the Montgomery ladder
* Daniel J. Bernstein, Tanja Lange
* https://eprint.iacr.org/2017/293.pdf
*
* [SQUARED] Elligator Squared
* Mehdi Tibouchi
* https://eprint.iacr.org/2014/043.pdf
*
* [SEC1] SEC 1 - Standards for Efficient Cryptography Group
* Certicom Research
* https://www.secg.org/sec1-v2.pdf
*
* [SEC2] SEC 2: Recommended Elliptic Curve Domain Parameters
* Certicom Research
* https://www.secg.org/sec2-v2.pdf
*
* [SIDE1] Elliptic Curves and Side-Channel Attacks
* Marc Joye
* https://pdfs.semanticscholar.org/8d69/9645033e25d74fcfd4cbf07a770d2e943e14.pdf
*
* [BLIND] Side-Channel Analysis on Blinding Regular Scalar Multiplications
* B. Feix, M. Roussellet, A. Venelli
* https://eprint.iacr.org/2014/191.pdf
*
* [ALT] Alternative Elliptic Curve Representations
* R. Struik
* https://tools.ietf.org/id/draft-ietf-lwig-curve-representations-02.html
*
* [ARITH1] Arithmetic of Elliptic Curves
* Christophe Doche, Tanja Lange
* Handbook of Elliptic and Hyperelliptic Curve Cryptography
* Page 267, Section 13 (978-1-58488-518-4)
* https://hyperelliptic.org/HEHCC/index.html
*
* [ARITH2] The Arithmetic of Elliptic Curves, 2nd Edition
* Joseph H. Silverman
* http://www.pdmi.ras.ru/~lowdimma/BSD/Silverman-Arithmetic_of_EC.pdf
*
* [EFD] Explicit-Formulas Database
* Daniel J. Bernstein, Tanja Lange
* https://hyperelliptic.org/EFD/index.html
*
* [SAFE] SafeCurves: choosing safe curves for elliptic-curve cryptography
* Daniel J. Bernstein
* https://safecurves.cr.yp.to/
*
* [4GLV] Refinement of the Four-Dimensional GLV Method on Elliptic Curves
* Hairong Yi, Yuqing Zhu, and Dongdai Lin
* http://www.site.uottawa.ca/~cadams/papers/prepro/paper_19_slides.pdf
*
* [SSWU1] Efficient Indifferentiable Hashing into Ordinary Elliptic Curves
* E. Brier, J. Coron, T. Icart, D. Madore, H. Randriam, M. Tibouchi
* https://eprint.iacr.org/2009/340.pdf
*
* [SSWU2] Rational points on certain hyperelliptic curves over finite fields
* Maciej Ulas
* https://arxiv.org/abs/0706.1448
*
* [H2EC] Hashing to Elliptic Curves
* A. Faz-Hernandez, S. Scott, N. Sullivan, R. S. Wahby, C. A. Wood
* https://git.io/JeWz6
* https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve
*
* [SVDW1] Construction of Rational Points on Elliptic Curves
* A. Shallue, C. E. van de Woestijne
* https://works.bepress.com/andrew_shallue/1/download/
*
* [SVDW2] Indifferentiable Hashing to Barreto-Naehrig Curves
* Pierre-Alain Fouque, Mehdi Tibouchi
* https://www.di.ens.fr/~fouque/pub/latincrypt12.pdf
*
* [SVDW3] Covert ECDH over secp256k1
* Pieter Wuille
* https://gist.github.com/sipa/29118d3fcfac69f9930d57433316c039
*
* [MONT2] Montgomery Curve (wikipedia)
* https://en.wikipedia.org/wiki/Montgomery_curve
*
* [MONT3] Montgomery Curves and their arithmetic
* C. Costello, B. Smith
* https://eprint.iacr.org/2017/212.pdf
*
* [ELL2] Elliptic-curve points indistinguishable from uniform random strings
* D. Bernstein, M. Hamburg, A. Krasnova, T. Lange
* https://elligator.cr.yp.to/elligator-20130828.pdf
*
* [RFC7748] Elliptic Curves for Security
* A. Langley, M. Hamburg, S. Turner
* https://tools.ietf.org/html/rfc7748
*
* [TWISTED] Twisted Edwards Curves
* D. Bernstein, P. Birkner, M. Joye, T. Lange, C. Peters
* https://eprint.iacr.org/2008/013.pdf
*
* [ELL1] Injective Encodings to Elliptic Curves
* P. Fouque, A. Joux, M. Tibouchi
* https://eprint.iacr.org/2013/373.pdf
*
* [ISOGENY] Twisting Edwards curves with isogenies
* Mike Hamburg
* https://www.shiftleft.org/papers/isogeny/isogeny.pdf
*
* [RFC8032] Edwards-Curve Digital Signature Algorithm (EdDSA)
* S. Josefsson, SJD AB, I. Liusvaara
* https://tools.ietf.org/html/rfc8032
*
* [SCHNORR] Schnorr Signatures for secp256k1
* Pieter Wuille
* https://github.com/sipa/bips/blob/d194620/bip-schnorr.mediawiki
*
* [BIP340] Schnorr Signatures for secp256k1
* Pieter Wuille, Jonas Nick, Tim Ruffing
* https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
*
* [JCEN12] Efficient Software Implementation of Public-Key Cryptography
* on Sensor Networks Using the MSP430X Microcontroller
* C. P. L. Gouvea, L. B. Oliveira, J. Lopez
* http://conradoplg.cryptoland.net/files/2010/12/jcen12.pdf
*
* [FIPS186] Federal Information Processing Standards Publication
* National Institute of Standards and Technology
* https://tinyurl.com/fips-186-3
*
* [RFC5639] Elliptic Curve Cryptography (ECC) Brainpool
* Standard Curves and Curve Generation
* M. Lochter, BSI, J. Merkle
* https://tools.ietf.org/html/rfc5639
*
* [TWISTEQ] Twisted Edwards & Short Weierstrass Equivalence
* Christopher Jeffrey
* https://gist.github.com/chjj/16ba7fa08d64e8dda269a9fe5b2a8bbc
*
* [ECPM] Elliptic Curve Point Multiplication (wikipedia)
* https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication
*/
'use strict';
const {custom} = __node_require__(33 /* '../internal/custom' */);
const BN = __node_require__(31 /* '../bn' */);
/*
* Constants
*/
const types = {
AFFINE: 0,
JACOBIAN: 1,
PROJECTIVE: 2,
EXTENDED: 3
};
const jsfIndex = [
-3, // -1 -1
-1, // -1 0
-5, // -1 1
-7, // 0 -1
0, // 0 0
7, // 0 1
5, // 1 -1
1, // 1 0
3 // 1 1
];
const USE_FIXED = false;
let uid = 0;
/**
* Curve
*/
class Curve {
constructor(Point, type, conf) {
this.Point = null;
this.id = null;
this.uid = uid++;
this.ossl = null;
this.type = 'base';
this.endian = 'be';
this.hash = null;
this.prefix = null;
this.context = false;
this.prime = null;
this.p = null;
this.red = null;
this.fieldSize = 0;
this.fieldBits = 0;
this.adjustedSize = 0;
this.signBit = 0;
this.mask = 0;
this.n = null;
this.h = null;
this.q = null;
this.z = null;
this.g = null;
this.nh = null;
this.scalarSize = 0;
this.scalarBits = 0;
this.zero = null;
this.one = null;
this.two = null;
this.three = null;
this.four = null;
this.i2 = null;
this.i3 = null;
this.i4 = null;
this.i6 = null;
this.torsion = null;
this.endo = null;
this.hi = null;
this._init(Point, type, conf);
}
_init(Point, type, conf) {
assert(typeof Point === 'function');
assert(typeof type === 'string');
assert(conf && typeof conf === 'object');
assert(conf.red == null || (conf.red instanceof BN.Red));
assert(conf.p != null, 'Must pass a prime.');
assert(conf.id == null || typeof conf.id === 'string');
assert(conf.ossl == null || typeof conf.ossl === 'string');
assert(conf.endian == null || typeof conf.endian === 'string');
assert(conf.hash == null || typeof conf.hash === 'string');
assert(conf.prefix == null || typeof conf.prefix === 'string');
assert(conf.context == null || typeof conf.context === 'boolean');
assert(conf.prime == null || typeof conf.prime === 'string');
assert(conf.torsion == null || Array.isArray(conf.torsion));
// Point class.
this.Point = Point;
// Meta.
this.id = conf.id || null;
this.ossl = conf.ossl || null;
this.type = type;
this.endian = conf.endian || (type === 'short' ? 'be' : 'le');
this.hash = conf.hash || null;
this.prefix = conf.prefix ? Buffer.from(conf.prefix, 'binary') : null;
this.context = conf.context || false;
this.prime = conf.prime || null;
// Prime.
this.p = BN.fromJSON(conf.p);
// Reduction.
if (conf.red) {
this.red = conf.red;
} else {
// Use Montgomery when there is no fast reduction for the prime.
this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p);
this.red.precompute();
}
// Precalculate encoding length.
this.fieldSize = this.p.byteLength();
this.fieldBits = this.p.bitLength();
this.adjustedSize = this.fieldSize + ((this.fieldBits & 7) === 0);
this.signBit = this.adjustedSize * 8 - 1;
this.mask = 0xff;
if ((this.fieldBits & 7) !== 0)
this.mask = (1 << (this.fieldBits & 7)) - 1;
// Curve configuration, optional.
this.n = BN.fromJSON(conf.n || '0');
this.h = BN.fromJSON(conf.h || '1');
this.q = this.n.mul(this.h);
this.z = BN.fromJSON(conf.z || '0').toRed(this.red);
this.g = null;
this.nh = this.n.ushrn(1);
this.scalarSize = this.n.byteLength();
this.scalarBits = this.n.bitLength();
// Useful for many curves.
this.zero = new BN(0).toRed(this.red);
this.one = new BN(1).toRed(this.red);
this.two = new BN(2).toRed(this.red);
this.three = new BN(3).toRed(this.red);
this.four = new BN(4).toRed(this.red);
// Inverses.
this.i2 = this.two.redInvert();
this.i3 = this.three.redInvert();
this.i4 = this.i2.redSqr();
this.i6 = this.i2.redMul(this.i3);
// Torsion.
this.torsion = new Array(this.h.word(0));
for (let i = 0; i < this.torsion.length; i++)
this.torsion[i] = this.point();
// Endomorphism.
this.endo = null;
// Cache.
this.hi = null;
// Memoize.
this._scale = memoize(this._scale, this);
this.isIsomorphic = memoize(this.isIsomorphic, this);
this.isIsogenous = memoize(this.isIsogenous, this);
// Sanity checks.
assert(this.p.sign() > 0 && this.p.isOdd());
assert(this.n.sign() >= 0);
assert(this.h.sign() > 0 && this.h.cmpn(255) <= 0);
assert(this.endian === 'be' || this.endian === 'le');
return this;
}
_finalize(conf) {
assert(conf && typeof conf === 'object');
// Create base point.
this.g = conf.g ? this.pointFromJSON(conf.g) : this.point();
// Parse small order points.
if (conf.torsion) {
assert(conf.torsion.length === this.torsion.length);
for (let i = 0; i < this.torsion.length; i++)
this.torsion[i] = this.pointFromJSON(conf.torsion[i]);
}
return this;
}
_findTorsion() {
// Find all torsion points by grinding.
assert(!this.n.isZero());
const h = this.h.word(0);
const x = this.one.redNeg();
const out = [this.point()];
const set = new Set();
let len = h;
while (out.length < len) {
let p;
x.redIAdd(this.one);
try {
p = this.pointFromX(x.clone());
} catch (e) {
continue;
}
try {
p = p.mul(this.n);
} catch (e) {
len = 2;
continue;
}
if (p.isInfinity())
continue;
p.normalize();
for (const point of [p, p.neg()]) {
const key = point.key();
if (!set.has(key)) {
out.push(point);
set.add(key);
}
}
}
out.sort((a, b) => a.cmp(b));
while (out.length < h)
out.push(this.point());
return out;
}
_fixedMul(p, k) {
// Fixed-base method for point multiplication.
//
// [ECPM] "Windowed method".
// [GECC] Page 95, Section 3.3.
//
// Windows are appropriately shifted to avoid any
// doublings. This reduces a 256 bit multiplication
// down to 64 additions with a window size of 4.
assert(p instanceof Point);
assert(k instanceof BN);
assert(p.pre && p.pre.windows);
// Get precomputed windows.
const {width, points} = p._getWindows(0, 0);
// Recompute window size.
const size = 1 << width;
// Recompute steps.
const bits = k.bitLength();
const steps = ((bits + width - 1) / width) >>> 0;
// Multiply.
let acc = this.jpoint();
for (let i = 0; i < steps; i++) {
const bits = k.bits(i * width, width);
acc = acc.add(points[i * size + bits]);
}
// Adjust sign.
if (k.isNeg())
acc = acc.neg();
return acc;
}
_fixedNafMul(p, k) {
// Fixed-base NAF windowing method for point multiplication.
//
// [GECC] Algorithm 3.42, Page 105, Section 3.3.
assert(p instanceof Point);
assert(k instanceof BN);
assert(p.pre && p.pre.doubles);
// Get precomputed doubles.
const {step, points} = p._getDoubles(0, 0);
// Get fixed NAF (in a more windowed form).
const naf = getFixedNAF(k, 2, k.bitLength() + 1, step);
// Compute steps.
const I = ((1 << (step + 1)) - (step % 2 === 0 ? 2 : 1)) / 3;
// Multiply.
let a = this.jpoint();
let b = this.jpoint();
for (let i = I; i > 0; i--) {
for (let j = 0; j < naf.length; j++) {
const nafW = naf[j];
if (nafW === i)
b = b.add(points[j]);
else if (nafW === -i)
b = b.sub(points[j]);
}
a = a.add(b);
}
return a;
}
_wnafMul(w, p, k) {
// Window NAF method for point multiplication.
//
// [GECC] Algorithm 3.36, Page 100, Section 3.3.
assert(p instanceof Point);
assert(k instanceof BN);
// Precompute window.
const {width, points} = p._safeNAF(w);
// Get NAF form.
const naf = getNAF(k, width, k.bitLength() + 1);
// Add `this`*(N+1) for every w-NAF index.
let acc = this.jpoint();
for (let i = naf.length - 1; i >= 0; i--) {
const z = naf[i];
if (i !== naf.length - 1)
acc = acc.dbl();
if (z > 0)
acc = acc.add(points[(z - 1) >> 1]);
else if (z < 0)
acc = acc.sub(points[(-z - 1) >> 1]);
}
return acc;
}
_wnafMulAdd(w, points, coeffs) {
// Multiple point multiplication, also known
// as "Shamir's trick" (with interleaved NAFs).
//
// [GECC] Algorithm 3.48, Page 109, Section 3.3.3.
// Algorithm 3.51, Page 112, Section 3.3.
//
// This is particularly useful for signature
// verifications and mutiplications after an
// endomorphism split.
assert((w >>> 0) === w);
assert(Array.isArray(points));
assert(Array.isArray(coeffs));
assert(points.length === coeffs.length);
const length = points.length;
const wnd = new Array(length);
const naf = new Array(length);
// Check arrays and calculate size.
let max = 0;
for (let i = 0; i < length; i++) {
const point = points[i];
const coeff = coeffs[i];
assert(point instanceof Point);
assert(coeff instanceof BN);
if (i > 0 && point.type !== points[i - 1].type)
throw new Error('Cannot mix points.');
// Avoid sparse arrays.
wnd[i] = null;
naf[i] = null;
// Compute max scalar size.
max = Math.max(max, coeff.bitLength() + 1);
}
// Compute NAFs.
let ppoint = null;
let pcoeff = null;
let len = 0;
for (let i = 0; i < length; i++) {
const point = points[i];
const coeff = coeffs[i];
const pre = point._getNAF(0);
// Use precomputation if available.
if (pre) {
wnd[len] = pre.points;
naf[len] = getNAF(coeff, pre.width, max);
len += 1;
continue;
}
// Save last non-precomputed point.
if (!ppoint) {
ppoint = point;
pcoeff = coeff;
continue;
}
// Compute JSF in NAF form.
wnd[len] = ppoint._getJNAF(point);
naf[len] = getJNAF(pcoeff, coeff, max);
ppoint = null;
pcoeff = null;
len += 1;
}
// Regular NAF for odd points.
if (ppoint) {
const nafw = ppoint._safeNAF(w);
wnd[len] = nafw.points;
naf[len] = getNAF(pcoeff, nafw.width, max);
len += 1;
}
// Multiply and add.
let acc = this.jpoint();
for (let i = max - 1; i >= 0; i--) {
if (i !== max - 1)
acc = acc.dbl();
for (let j = 0; j < len; j++) {
const z = naf[j][i];
if (z > 0)
acc = acc.add(wnd[j][(z - 1) >> 1]);
else if (z < 0)
acc = acc.sub(wnd[j][(-z - 1) >> 1]);
}
}
return acc;
}
_endoWnafMulAdd(points, coeffs) {
throw new Error('Not implemented.');
}
_scale(curve, invert) {
assert(curve instanceof Curve);
assert(curve.p.eq(this.p));
switch (curve.type) {
case 'short':
return this._scaleShort(curve, invert);
case 'mont':
return this._scaleMont(curve, invert);
case 'edwards':
return this._scaleEdwards(curve, invert);
default:
throw new Error('Not implemented.');
}
}
_scaleShort(curve, invert) {
throw new Error('Not implemented.');
}
_scaleMont(curve, invert) {
throw new Error('Not implemented.');
}
_scaleEdwards(curve, invert) {
throw new Error('Not implemented.');
}
isElliptic() {
throw new Error('Not implemented.');
}
jinv() {
throw new Error('Not implemented.');
}
isComplete() {
return false;
}
precompute(rng) {
assert(!this.g.isInfinity(), 'Must have base point.');
assert(!this.n.isZero(), 'Must have order.');
this.g.precompute(this.n.bitLength(), rng);
return this;
}
scalar(num, base, endian) {
const k = new BN(num, base, endian);
assert(!k.red);
if (this.n.isZero())
return k;
return k.imod(this.n);
}
field(num, base, endian) {
const x = BN.cast(num, base, endian);
if (x.red)
return x.forceRed(this.red);
return x.toRed(this.red);
}
point(x, y) {
throw new Error('Not implemented.');
}
jpoint(x, y, z) {
throw new Error('Not implemented.');
}
xpoint(x, z) {
throw new Error('Not implemented.');
}
cpoint(xx, xz, yy, yz) {
assert(xx instanceof BN);
assert(xz instanceof BN);
assert(yy instanceof BN);
assert(yz instanceof BN);
if (xz.isZero() || yz.isZero())
return this.point();
const z = xz.redMul(yz).redInvert();
const x = xx.redMul(yz).redMul(z);
const y = yy.redMul(xz).redMul(z);
return this.point(x, y);
}
solveX2(y) {
throw new Error('Not implemented.');
}
solveX(y) {
return this.solveX2(y).redSqrt();
}
solveY2(x) {
throw new Error('Not implemented.');
}
solveY(x) {
return this.solveY2(x).redSqrt();
}
validate(point) {
throw new Error('Not implemented.');
}
pointFromX(x, sign) {
throw new Error('Not implemented.');
}
pointFromY(y, sign) {
throw new Error('Not implemented.');
}
isIsomorphic(curve) {
throw new Error('Not implemented.');
}
isIsogenous(curve) {
throw new Error('Not implemented.');
}
pointFromShort(point) {
throw new Error('Not implemented.');
}
pointFromMont(point, sign) {
throw new Error('Not implemented.');
}
pointFromEdwards(point) {
throw new Error('Not implemented.');
}
pointFromUniform(u) {
throw new Error('Not implemented.');
}
pointToUniform(p) {
throw new Error('Not implemented.');
}
pointFromHash(bytes, pake = false) {
// [H2EC] "Roadmap".
assert(Buffer.isBuffer(bytes));
assert(typeof pake === 'boolean');
if (bytes.length !== this.fieldSize * 2)
throw new Error('Invalid hash size.');
// Random oracle encoding.
// Ensure a proper distribution.
const s1 = bytes.slice(0, this.fieldSize);
const s2 = bytes.slice(this.fieldSize);
const u1 = this.decodeUniform(s1);
const u2 = this.decodeUniform(s2);
const p1 = this.pointFromUniform(u1);
const p2 = this.pointFromUniform(u2);
const p3 = p1.add(p2);
return pake ? p3.mulH() : p3;
}
pointToHash(p, subgroup, rng) {
// [SQUARED] Algorithm 1, Page 8, Section 3.3.
assert(p instanceof this.Point);
assert((subgroup >>> 0) === subgroup);
// Add a random torsion component.
const i = subgroup % this.torsion.length;
const p0 = p.add(this.torsion[i]);
// Average Cost (R = sqrt):
//
// SSWU (~4 iterations) => 8I + 16R
// SVDW (~4 iterations) => 12I + 28R
// Elligator 1 (~2 iterations) => 6I + 10R
// Elligator 2 (~2 iterations) => 4I + 6R
// Ristretto (~1 iteration) => 1I + 2R + h*1R
for (;;) {
const u1 = this.randomField(rng);
const p1 = this.pointFromUniform(u1);
// Avoid 2-torsion points:
// Short Weierstrass: ((A / 3) / B, 0)
// Montgomery: (0, 0)
// Twisted Edwards: (0, -1)
if (p1.neg().eq(p1))
continue;
const p2 = p0.sub(p1);
const hint = randomInt(rng);
let u2;
try {
u2 = this.pointToUniform(p2, hint & 15);
} catch (e) {
if (e.message === 'Invalid point.')
continue;
throw e;
}
const s1 = this.encodeUniform(u1, hint >>> 8);
const s2 = this.encodeUniform(u2, hint >>> 16);
return Buffer.concat([s1, s2]);
}
}
randomScalar(rng) {
const max = this.n.isZero() ? this.p : this.n;
return BN.random(rng, 1, max);
}
randomField(rng) {
return BN.random(rng, 1, this.p).toRed(this.red);
}
randomPoint(rng) {
let p;
for (;;) {
const x = this.randomField(rng);
const sign = (randomInt(rng) & 1) !== 0;
try {
p = this.pointFromX(x, sign);
} catch (e) {
continue;
}
assert(p.validate());
return p.mulH();
}
}
mulAll(points, coeffs) {
return this.jmulAll(points, coeffs);
}
jmulAll(points, coeffs) {
assert(Array.isArray(points));
assert(points.length === 0 || (points[0] instanceof Point));
// Multiply with endomorphism if we're using affine points.
if (this.endo && points.length > 0 && points[0].type === types.AFFINE)
return this._endoWnafMulAdd(points, coeffs);
// Otherwise, a regular Shamir's trick.
return this._wnafMulAdd(5, points, coeffs);
}
mulH(k) {
assert(k instanceof BN);
return this.imulH(k.clone());
}
imulH(k) {
assert(k instanceof BN);
assert(!k.red);
const word = this.h.word(0);
// Optimize for powers of two.
if ((word & (word - 1)) === 0) {
const bits = this.h.bitLength();
return k.iushln(bits - 1).imod(this.n);
}
return k.imuln(word).imod(this.n);
}
normalizeAll(points) {
assert(Array.isArray(points));
const len = points.length;
const z = new Array(len);
for (let i = 0; i < len; i++) {
const p = points[i];
assert(p instanceof Point);
assert(p.curve === this);
if (p.type === types.AFFINE) {
z[i] = this.one;
continue;
}
z[i] = p.z;
}
const zi = this.red.invertAll(z);
const out = new Array(len);
for (let i = 0; i < len; i++)
out[i] = points[i].scale(zi[i]);
return out;
}
affinizeAll(points) {
return this.normalizeAll(points);
}
clamp(scalar) {
// [RFC7748] Page 8, Section 5.
// [RFC8032] Section 5.1.5 & 5.2.5.
assert(Buffer.isBuffer(scalar));
assert(scalar.length === this.scalarSize);
assert(this.scalarSize <= this.fieldSize);
let top = (this.fieldBits & 7) || 8;
let lsb = 0;
let msb = this.scalarSize - 1;
// Swap endianness.
if (this.endian === 'be')
[lsb, msb] = [msb, lsb];
// Adjust for low order.
if (this.scalarSize < this.fieldSize)
top = 8;
// Ensure a multiple of the cofactor.
scalar[lsb] &= -this.h.word(0) & 0xff;
// Clamp to the prime.
scalar[msb] &= (1 << top) - 1;
// Set the high bit.
scalar[msb] |= 1 << (top - 1);
return scalar;
}
splitHash(bytes) {
// [RFC8032] Section 5.1.6 & 5.2.6.
assert(Buffer.isBuffer(bytes));
assert(bytes.length === this.adjustedSize * 2);
assert(this.scalarSize <= this.adjustedSize);
let off = 0;
if (this.endian === 'be')
off = this.adjustedSize - this.scalarSize;
const scalar = bytes.slice(off, off + this.scalarSize);
const prefix = bytes.slice(this.adjustedSize);
this.clamp(scalar);
return [scalar, prefix];
}
encodeField(x) {
// [SEC1] Page 12, Section 2.3.5.
assert(x instanceof BN);
assert(!x.red);
return x.encode(this.endian, this.fieldSize);
}
decodeField(bytes) {
// [SEC1] Page 13, Section 2.3.6.
assert(Buffer.isBuffer(bytes));
if (bytes.length !== this.fieldSize)
throw new Error('Invalid field element size.');
return BN.decode(bytes, this.endian);
}
encodeAdjusted(x) {
assert(x instanceof BN);
assert(!x.red);
return x.encode(this.endian, this.adjustedSize);
}
decodeAdjusted(bytes) {
assert(Buffer.isBuffer(bytes));
if (bytes.length !== this.adjustedSize)
throw new Error('Invalid field element size.');
return BN.decode(bytes, this.endian);
}
encodeScalar(k) {
// [SEC1] Page 13, Section 2.3.7.
assert(k instanceof BN);
assert(!k.red);
return k.encode(this.endian, this.scalarSize);
}
decodeScalar(bytes) {
// [SEC1] Page 14, Section 2.3.8.
assert(Buffer.isBuffer(bytes));
if (bytes.length !== this.scalarSize)
throw new Error('Invalid scalar size.');
return BN.decode(bytes, this.endian);
}
encodeClamped(k) {
// [RFC7748] Page 8, Section 5.
// [RFC8032] Section 5.1.5 & 5.2.5.
return this.clamp(this.encodeScalar(k));
}
decodeClamped(bytes) {
// [RFC7748] Page 8, Section 5.
// [RFC8032] Section 5.1.5 & 5.2.5.
assert(Buffer.isBuffer(bytes));
if (bytes.length !== this.scalarSize)
throw new Error('Invalid scalar size.');
const clamped = this.clamp(Buffer.from(bytes));
return BN.decode(clamped, this.endian);
}
encodeUniform(x, bits) {
assert(x instanceof BN);
assert((bits >>> 0) === bits);
const msb = this.endian === 'le' ? this.fieldSize - 1 : 0;
const bytes = x.fromRed().encode(this.endian, this.fieldSize);
bytes[msb] |= (bits & ~this.mask) & 0xff;
return bytes;
}
decodeUniform(bytes) {
assert(Buffer.isBuffer(bytes));
if (bytes.length !== this.fieldSize)
throw new Error('Invalid field size.');
const x = BN.decode(bytes, this.endian);
x.iumaskn(this.fieldBits);
return x.toRed(this.red);
}
encodePoint(point, compact) {
assert(point instanceof Point);
return point.encode(compact);
}
decodePoint(bytes) {
throw new Error('Not implemented.');
}
encodeX(point) {
throw new Error('Not implemented.');
}
decodeX(bytes) {
throw new Error('Not implemented.');
}
decodeEven(bytes) {
throw new Error('Not implemented.');
}
decodeSquare(bytes) {
throw new Error('Not implemented.');
}
toShort() {
throw new Error('Not implemented.');
}
toMont(b0) {
throw new Error('Not implemented.');
}
toEdwards(a0) {
throw new Error('Not implemented.');
}
pointToJSON(point, pre) {
assert(point instanceof Point);
return point.toJSON(pre);
}
pointFromJSON(json) {
throw new Error('Not implemented.');
}
toJSON(pre) {
let prefix, context;
let n, z, endo;
if (this.type === 'edwards') {
prefix = this.prefix ? this.prefix.toString() : null;
context = this.context;
}
if (!this.n.isZero())
n = this.n.toJSON();
if (!this.z.isZero()) {
z = this.z.fromRed();
if (this.z.redIsHigh())
z.isub(this.p);
z = z.toString(16);
}
if (this.endo)
endo = this.endo.toJSON();
return {
id: this.id,
ossl: this.ossl,
type: this.type,
endian: this.endian,
hash: this.hash,
prefix,
context,
prime: this.prime,
p: this.p.toJSON(),
a: undefined,
b: undefined,
d: undefined,
n,
h: this.h.toString(16),
s: undefined,
z,
c: undefined,
g: this.g.toJSON(pre),
endo
};
}
static fromJSON(json) {
return new this(json);
}
}
/**
* Point
*/
class Point {
constructor(curve, type) {
assert(curve instanceof Curve);
assert((type >>> 0) === type);
this.curve = curve;
this.type = type;
this.pre = null;
}
_init() {
throw new Error('Not implemented.');
}
_safeNAF(width) {
assert((width >>> 0) === width);
if (this.pre && this.pre.naf)
return this.pre.naf;
if (width === 0)
return null;
const size = 1 << (width - 2);
const points = new Array(size);
const p = this.toJ();
const dbl = size === 1 ? null : p.dbl();
points[0] = p;
for (let i = 1; i < size; i++)
points[i] = points[i - 1].add(dbl);
return new NAF(width, points);
}
_getNAF(width) {
assert((width >>> 0) === width);
if (this.pre && this.pre.naf)
return this.pre.naf;
if (width === 0)
return null;
const odds = this._safeNAF(width).points;
const points = this.curve.affinizeAll(odds);
return new NAF(width, points);
}
_getWindows(width, bits) {
assert((width >>> 0) === width);
assert((bits >>> 0) === bits);
if (this.pre && this.pre.windows)
return this.pre.windows;
if (width === 0)
return null;
const size = 1 << width;
const steps = ((bits + width - 1) / width) >>> 0;
const wnds = new Array(steps * size);
let g = this.toJ();
for (let i = 0; i < steps; i++) {
wnds[i * size] = this.curve.jpoint();
for (let j = 1; j < size; j++)
wnds[i * size + j] = wnds[i * size + j - 1].add(g);
g = g.dblp(width);
}
const points = this.curve.affinizeAll(wnds);
return new Windows(width, bits, points);
}
_getDoubles(step, power) {
assert((step >>> 0) === step);
assert((power >>> 0) === power);
if (this.pre && this.pre.doubles)
return this.pre.doubles;
if (step === 0)
return null;
const len = Math.ceil(power / step) + 1;
const dbls = new Array(len);
let acc = this.toJ();
let k = 0;
dbls[k++] = acc;
for (let i = 0; i < power; i += step) {
for (let j = 0; j < step; j++)
acc = acc.dbl();
dbls[k++] = acc;
}
assert(k === len);
const points = this.curve.affinizeAll(dbls);
return new Doubles(step, points);
}
_getBeta() {
return null;
}
_getBlinding(rng) {
if (this.pre && this.pre.blinding)
return this.pre.blinding;
if (!rng)
return null;
if (this.curve.n.isZero())
return null;
// Pregenerate a random blinding value:
//
// blind = random integer in [1,n-1]
// unblind = G * blind
//
// We intend to subtract the blinding value
// from scalars before multiplication. We
// can add the unblinding point once the
// multiplication is complete.
const blind = this.curve.randomScalar(rng);
const unblind = this.mul(blind);
return new Blinding(blind, unblind);
}
_hasWindows(k) {
assert(k instanceof BN);
if (!this.pre || !this.pre.windows)
return false;
const {width, bits} = this.pre.windows;
const steps = ((bits + width - 1) / width) >>> 0;
return k.bitLength() <= steps * width;
}
_hasDoubles(k) {
assert(k instanceof BN);
if (!this.pre || !this.pre.doubles)
return false;
const {step, points} = this.pre.doubles;
const power = k.bitLength() + 1;
return points.length >= Math.ceil(power / step) + 1;
}
_getJNAF(point) {
assert(point instanceof Point);
assert(point.type === this.type);
// Create comb for JSF.
return [
this, // 1
this.add(point), // 3
this.sub(point), // 5
point // 7
];
}
_blind(k, rng) {
// [SIDE1] Page 5, Section 4.
// [BLIND] Page 20, Section 7.
assert(k instanceof BN);
assert(!k.red);
// Scalar splitting (requires precomputation).
//
// Blind a multiplication by first subtracting
// a blinding value from the scalar. Example:
//
// b = random integer in [1,n-1]
// B = P * b (precomputed)
// Q = P * (k - b) + B
//
// Note that Joye describes a different method
// (multiplier randomization) which computes:
//
// B = random point in E
// Q = (P + B) * k - B * k
//
// Our method is more similar to the "scalar
// splitting" technique described in the
// second source above.
//
// The blinding value and its corresponding
// point are randomly generated and computed
// on boot. As long as an attacker is not
// able to observe the boot, this should give
// a decent bit of protection against various
// channel attacks.
if (this.pre && this.pre.blinding) {
const {blind, unblind} = this.pre.blinding;
const t = k.sub(blind);
return [this, t, unblind];
}
// Randomization is not possible without
// an RNG. Do a normal multiplication.
if (!rng)
return [this, k, null];
// If we have no precomputed blinding
// factor, there are two possibilities
// for randomization:
//
// 1. Randomize the multiplier by adding
// a random multiple of `n`.
//
// 2. Re-scale the point itself by a
// random factor.
//
// The first option can be accomplished
// with some like:
//
// a = random integer in [1,n-1]
// r = a * n
// Q = P * (k + r)
//
// The second is accomplished with:
//
// a = random element in F(p)
// R = (x * a^2, y * a^3, z * a)
// Q = R * k
//
// If we have precomputed doubles / naf
// points, we opt for the first method
// to avoid randomizing everything.
if (this.pre) {
if (this.curve.n.isZero())
return [this, k, null];
const a = this.curve.randomScalar(rng);
const r = a.mul(this.curve.n);
const t = r.iadd(k);
return [this, t, null];
}
// If there is no precomputation _at all_,
// we opt for the second method.
const p = this.randomize(rng);
return [p, k, null];
}
clone() {
throw new Error('Not implemented.');
}
precompute(bits, rng) {
assert((bits >>> 0) === bits);
if (!this.pre)
this.pre = new Precomp();
if (!this.pre.naf)
this.pre.naf = this._getNAF(9);
if (USE_FIXED && !this.pre.windows)
this.pre.windows = this._getWindows(4, bits);
if (!this.pre.doubles)
this.pre.doubles = this._getDoubles(4, bits + 1);
if (!this.pre.beta)
this.pre.beta = this._getBeta();
if (!this.pre.blinding)
this.pre.blinding = this._getBlinding(rng);
return this;
}
validate() {
return this.curve.validate(this);
}
normalize() {
return this;
}
scale(a) {
throw new Error('Not implemented.');
}
randomize(rng) {
const z = this.curve.randomField(rng);
return this.scale(z);
}
neg() {
throw new Error('Not implemented.');
}
add(point) {
throw new Error('Not implemented.');
}
sub(point) {
assert(point instanceof Point);
return this.add(point.neg());
}
dbl() {
throw new Error('Not implemented.');
}
dblp(pow) {
// Repeated doubling. This can
// be optimized by child classes.
assert((pow >>> 0) === pow);
let r = this;
for (let i = 0; i < pow; i++)
r = r.dbl();
return r;
}
diffAddDbl(p, q) {
throw new Error('Not implemented.');
}
getX() {
throw new Error('Not implemented.');
}
getY() {
throw new Error('Not implemented.');
}
eq(point) {
throw new Error('Not implemented.');
}
cmp(point) {
throw new Error('Not implemented.');
}
isInfinity() {
throw new Error('Not implemented.');
}
isOrder2() {
throw new Error('Not implemented.');
}
isOdd() {
throw new Error('Not implemented.');
}
isEven() {
throw new Error('Not implemented.');
}
isSquare() {
throw new Error('Not implemented.');
}
eqX(x) {
throw new Error('Not implemented.');
}
eqR(x) {
throw new Error('Not implemented.');
}
isSmall() {
// Test whether the point is of small order.
if (this.isInfinity())
return false;
// P * h = O
return this.jmulH().isInfinity();
}
hasTorsion() {
// Test whether the point is in another subgroup.
if (this.isInfinity())
return false;
// P * n != O
return !this.jmul(this.curve.n).isInfinity();
}
order() {
// Calculate point order.
const {h, n} = this.curve;
let p = this.toJ();
let q = new BN(1);
while (!p.isInfinity()) {
q.iaddn(1);
if (q.cmp(h) > 0) {
q = n.clone();
break;
}
p = p.add(this);
}
return q;
}
mul(k) {
return this.jmul(k);
}
muln(k) {
return this.jmuln(k);
}
mulBlind(k, rng) {
return this.jmulBlind(k, rng);
}
mulAdd(k1, p2, k2) {
return this.jmulAdd(k1, p2, k2);
}
mulH() {
return this.jmulH();
}
div(k) {
return this.jdiv(k);
}
divn(k) {
return this.jdivn(k);
}
divH() {
return this.jdivH();
}
jmul(k) {
if (USE_FIXED && this._hasWindows(k))
return this.curve._fixedMul(this, k);
if (this._hasDoubles(k))
return this.curve._fixedNafMul(this, k);
if (this.curve.endo && this.type === types.AFFINE)
return this.curve._endoWnafMulAdd([this], [k]);
return this.curve._wnafMul(5, this, k);
}
jmuln(k) {
assert((k | 0) === k);
return this.jmul(new BN(k));
}
jmulBlind(k, rng = null) {
const [p, t, unblind] = this._blind(k, rng);
const q = p.jmul(t);
if (unblind)
return q.add(unblind);
return q;
}
jmulAdd(k1, p2, k2) {
if (this.curve.endo && this.type === types.AFFINE)
return this.curve._endoWnafMulAdd([this, p2], [k1, k2]);
return this.curve._wnafMulAdd(5, [this, p2], [k1, k2]);
}
jmulH() {
const word = this.curve.h.word(0);
// Optimize for powers of two.
if ((word & (word - 1)) === 0) {
const bits = this.curve.h.bitLength();
return this.toJ().dblp(bits - 1);
}
return this.jmul(this.curve.h);
}
jdiv(k) {
assert(k instanceof BN);
assert(!k.red);
return this.jmul(k.invert(this.curve.n));
}
jdivn(k) {
assert(!this.curve.n.isZero());
if (this.curve.h.cmpn(k) === 0)
return this.jdivH();
return this.jdiv(new BN(k));
}
jdivH() {
if (this.curve.n.isZero())
return this.toJ();
if (this.curve.h.cmpn(1) === 0)
return this.toJ();
if (this.curve.hi === null)
this.curve.hi = this.curve.h.invert(this.curve.n);
return this.jmul(this.curve.hi);
}
toP() {
return this.normalize();
}
toJ() {
return this;
}
toX() {
return this;
}
key() {
if (this.isInfinity())
return `${this.curve.uid}:oo`;
this.normalize();
const x = this.getX().toString(16);
const y = this.getY().toString(16);
return `${this.curve.uid}:${x},${y}`;
}
encode(compact) {
throw new Error('Not implemented.');
}
static decode(curve, bytes) {
throw new Error('Not implemented.');
}
encodeX() {
throw new Error('Not implemented.');
}
static decodeX(curve, bytes) {
throw new Error('Not implemented.');
}
static decodeEven(curve, bytes) {
throw new Error('Not implemented.');
}
static decodeSquare(curve, bytes) {
throw new Error('Not implemented.');
}
toJSON(pre) {
throw new Error('Not implemented.');
}
static fromJSON(curve, json) {
throw new Error('Not implemented.');
}
[custom]() {
return '<Point>';
}
}
/**
* ShortCurve
*/
class ShortCurve extends Curve {
constructor(conf) {
super(ShortPoint, 'short', conf);
this.a = BN.fromJSON(conf.a).toRed(this.red);
this.b = BN.fromJSON(conf.b).toRed(this.red);
this.c = BN.fromJSON(conf.c || '0').toRed(this.red);
this.ai = this.a.isZero() ? this.zero : this.a.redInvert();
this.zi = this.z.isZero() ? this.zero : this.z.redInvert();
this.zeroA = this.a.isZero();
this.threeA = this.a.eq(this.three.redNeg());
this.redN = this.n.toRed(this.red);
this.pmodn = this.p.clone();
this.highOrder = this.n.cmp(this.p) >= 0;
this.smallGap = false;
this._finalize(conf);
}
_finalize(conf) {
super._finalize(conf);
// Precalculate endomorphism.
if (conf.endo != null)
this.endo = Endo.fromJSON(this, conf.endo);
else
this.endo = this._getEndomorphism();
if (!this.n.isZero()) {
this.pmodn = this.p.mod(this.n);
// Check for Maxwell's trick (see eqR).
this.smallGap = this.p.div(this.n).cmpn(1) <= 0;
}
return this;
}
static _isomorphism(curveA, curveB, custom, odd) {
// Short Weierstrass Isomorphism.
//
// [GECC] Page 84, Section 3.1.5.
// [ARITH1] Page 274, Section 13.1.5.
// [ALT] Appendix F.3 (Isomorphic Mapping between Weierstrass Curves).
//
// Find `u` such that `a * u^4 = a'` and `b * u^6 = b'`.
//
// Transformation:
//
// u4 = a' / a
// u2 = +-sqrt(u4)
// u6 = u4 * u2
// a' = a * u4
// b' = b * u6
//
// Where `u2` is any root that is square.
//
// If a = 0, we can do:
//
// a' = 0
// b' = b'
//
// Where (b' / b)^(1 / 3) is square.
//
// If b = 0, we can do:
//
// a' = a'
// b' = 0
//
// Where sqrt(a' / a) is square.
assert(curveA instanceof BN);
assert(curveB instanceof BN);
assert(custom instanceof BN);
assert(odd == null || typeof odd === 'boolean');
assert(!curveA.isZero() || !curveB.isZero());
if (custom.isZero())
throw new Error('Invalid coefficient.');
if (curveA.isZero()) {
const customB = custom;
const u6 = customB.redDiv(curveB);
// Todo: allow index flag.
const u2 = uncube(u6);
// Already checked in uncube().
assert(u2.redJacobi() === 1);
return [curveA.clone(), customB.clone()];
}
if (curveB.isZero()) {
const customA = custom;
const u4 = customA.redDiv(curveA);
const u2 = u4.redSqrt();
// Todo: allow odd flag.
if (u2.redJacobi() !== 1)
u2.redINeg();
if (u2.redJacobi() !== 1)
throw new Error('Invalid `a` coefficient.');
return [customA.clone(), curveB.clone()];
}
const customA = custom;
const u4 = customA.redDiv(curveA);
const u2 = u4.redSqrt();
if (odd != null) {
if (u2.redIsOdd() !== odd)
u2.redINeg();
} else {
if (u2.redJacobi() !== 1)
u2.redINeg();
}
if (u2.redJacobi() !== 1)
throw new Error('Invalid `a` coefficient.');
const u6 = u4.redMul(u2);
const a = curveA.redMul(u4);
const b = curveB.redMul(u6);
assert(a.eq(customA));
return [a, b];
}
_short(a0, odd) {
return ShortCurve._isomorphism(this.a, this.b, a0, odd);
}
_mont(b0, odd) {
// Short Weierstrass->Montgomery Equivalence.
//
// [ARITH1] Page 286, Section 13.2.3.c.
// [SAFE] "Ladders".
//
// Transformation:
//
// r = A / (3 * B)
// s = +-sqrt(3 * r^2 + a)
// A = 3 * r / s
// B = 1 / s
const [r, s] = this._findRS(odd);
const b = s.redInvert();
const a = r.redMuln(3).redMul(b);
if (b0 != null)
return MontCurve._isomorphism(a, b, b0);
return [a, b];
}
_edwards(a0, odd) {
// Short Weierstrass->Twisted Edwards Equivalence.
//
// [TWISTEQ] Section 1.
//
// Transformation:
//
// r = (a' + d') / 6
// s = +-sqrt(3 * r^2 + a)
// a' = 3 * r + 2 * s
// d' = 3 * r - 2 * s
const [r, s] = this._findRS(odd);
const r3 = r.redMuln(3);
const s2 = s.redMuln(2);
const a = r3.redAdd(s2);
const d = r3.redSub(s2);
if (a0 != null)
return EdwardsCurve._isomorphism(a, d, a0);
return [a, d];
}
_findRS(sign) {
// Find `r` and `s` for equivalence.
//
// [ARITH1] Page 286, Section 13.2.3.c.
// [SAFE] "Ladders".
//
// Computation:
//
// r = solve(r^3 + a * r + b == 0, r)
// s = +-sqrt(3 * r^2 + a)
//
// Computing `r` is non-trivial. We need
// to solve `r^3 + a * r + b = 0`, but we
// don't have a polynomial solver, so we
// loop over random points until we find
// one with 2-torsion. Multiplying by the
// subgroup order should yield a point of
// ((A / 3) / B, 0) which is a solution.
assert(sign == null || typeof sign === 'boolean');
assert(this.h.word(0) >= 4);
assert(!this.n.isZero());
const x = this.one.redNeg();
let p;
for (;;) {
x.redIAdd(this.one);
try {
p = this.pointFromX(x.clone());
} catch (e) {
continue;
}
p = p.mul(this.n);
if (p.isInfinity())
continue;
if (!p.y.isZero())
continue;
break;
}
const r = p.x;
const r2 = r.redSqr();
const s = r2.redMuln(3).redIAdd(this.a).redSqrt();
if (sign != null) {
if (s.redIsOdd() !== sign)
s.redINeg();
}
return [r, s];
}
_scale0(a, b) {
// We can extract the isomorphism factors with:
//
// u4 = a' / a
// u6 = b' / b
// u2 = +-sqrt(u4)
// u = +-sqrt(u2)
// u3 = u2 * u
//
// `u2` should be picked such that `u4 * u2 = u6`.
//
// If a = 0, we can do:
//
// u6 = b' / b
// u2 = u6^(1 / 3)
// u = +-sqrt(u2)
// u3 = u2 * u
//
// Where `u2` is any root that is square.
//
// If b = 0, we can do:
//
// u4 = a' / a
// u2 = +-sqrt(u4)
// u = +-sqrt(u2)
// u3 = u2 * u
//
// Where `u2` is any root that is square.
assert(this.a.isZero() === a.isZero());
assert(this.b.isZero() === b.isZero());
if (this.a.isZero()) {
const u6 = this.b.redDiv(this.field(b));
// Todo: figure out how to check index.
const u2 = uncube(u6);
const u = u2.redSqrt();
const u3 = u2.redMul(u);
assert(u3.redSqr().eq(u6));
assert(!u.isZero());
return [u2, u3];
}
if (this.b.isZero()) {
const u4 = this.a.redDiv(this.field(a));
const u2 = u4.redSqrt();
// Todo: figure out how to check oddness.
if (u2.redJacobi() !== 1)
u2.redINeg();
const u = u2.redSqrt();
const u3 = u2.redMul(u);
assert(u3.redMul(u).eq(u4));
assert(!u.isZero());
return [u2, u3];
}
const u4 = this.a.redDiv(this.field(a));
const u6 = this.b.redDiv(this.field(b));
const u2 = u4.redSqrt();
if (!u4.redMul(u2).eq(u6))
u2.redINeg();
assert(u4.redMul(u2).eq(u6));
const u = u2.redSqrt();
const u3 = u2.redMul(u);
assert(!u.isZero());
return [u2, u3];
}
_scale1(x, y) {
// If base points are available, it is much
// easier, with:
//
// u2 = x' / x
// u3 = y' / y
// u = +-sqrt(u2)
//
// `u` should be picked such that `u2 * u = u3`.
const u2 = this.g.x.redDiv(this.field(x));
const u3 = this.g.y.redDiv(this.field(y));
const u = u2.redSqrt();
if (!u2.redMul(u).eq(u3))
u.redINeg();
assert(u2.redMul(u).eq(u3));
assert(!u.isZero());
return [u2, u3];
}
_scaleShort(curve) {
assert(curve instanceof ShortCurve);
if (this.g.isInfinity() || curve.g.isInfinity())
return this._scale0(curve.a, curve.b);
return this._scale1(curve.g.x, curve.g.y);
}
_scaleMont(curve) {
assert(curve instanceof MontCurve);
if (this.g.isInfinity() || curve.g.isInfinity()) {
const [a, b] = curve._short();
return this._scale0(a, b);
}
const {x, y} = curve.g;
const nx = x.redAdd(curve.a3).redMul(curve.bi);
const ny = y.redMul(curve.bi);
return this._scale1(nx, ny);
}
_scaleEdwards(curve) {
assert(curve instanceof EdwardsCurve);
if (this.g.isInfinity() || curve.g.isInfinity()) {
const [a, b] = curve._short();
return this._scale0(a, b);
}
const {x, y, z} = curve.g;
const a5 = curve.a.redMuln(5);
const d5 = curve.d.redMuln(5);
const dma = curve.d.redSub(curve.a);
const d5a = d5.redSub(curve.a);
const da5 = curve.d.redSub(a5);
const ypz = y.redAdd(z);
const ymz = y.redSub(z);
const xx = d5a.redMul(y).redIAdd(da5.redMul(z));
const xz = ymz.redMuln(12);
const yy = dma.redMul(ypz).redMul(z);
const yz = ymz.redMul(x).redIMuln(4);
const zi = xz.redMul(yz).redInvert();
const nx = xx.redMul(yz).redMul(zi);
const ny = yy.redMul(xz).redMul(zi);
return this._scale1(nx, ny);
}
_getEndomorphism(index = 0) {
// Compute endomorphism.
//
// [GECC] Example 3.76, Page 128, Section 3.5.
// No curve params.
if (this.n.isZero() || this.g.isInfinity())
return null;
// No efficient endomorphism.
if (!this.zeroA || this.p.modrn(3) !== 1 || this.n.modrn(3) !== 1)
return null;
// Solve beta^3 mod p = 1.
const [b1, b2] = this._getEndoRoots(this.p);
// Choose the smallest beta by default.
const beta = [b1, b2][index & 1].toRed(this.red);
// Solve lambda^3 mod n = 1.
const [l1, l2] = this._getEndoRoots(this.n);
// Choose the lambda matching selected beta.
// Note that P * lambda = (x * beta, y).
const p = this.point(this.g.x.redMul(beta), this.g.y);
let lambda;
if (this.g.mul(l1).eq(p)) {
lambda = l1;
} else {
assert(this.g.mul(l2).eq(p));
lambda = l2;
}
// Get basis vectors.
const basis = this._getEndoBasis(lambda);
// Precompute `g1` and `g2`.
const pre = this._getEndoPrecomp(basis);
return new Endo(beta, lambda, basis, pre);
}
_getEndoRoots(num) {
// Find roots for x^2 + x + 1 in F.
//
// [GECC] Example 3.76, Page 128, Section 3.5.
// [GLV] Page 192, Section 2 (Endomorphisms).
//
// The above document doesn't fully explain how
// to derive these and only "hints" at it, as
// mentioned by Hal Finney[1], but we're basically
// computing two possible cube roots of 1 here.
//
// Note that we could also compute[2]:
//
// beta = 2^((p - 1) / 3) mod p
// lambda = 3^((n - 1) / 3) mod n
//
// As an extension of Fermat's little theorem:
//
// g^(p - 1) mod p == 1
//
// It is suspected[3] this is how Hal Finney[4]
// computed his original endomorphism roots.
//
// @indutny's method for computing cube roots
// of unity[5] appears to be the method described
// on wikipedia[6][7].
//
// Sage produces the same solution:
//
// sage: solve(x^2 + x + 1 == 0, x)
// [x == -1/2*I*sqrt(3) - 1/2, x == 1/2*I*sqrt(3) - 1/2]
//
// This can be reduced to:
//
// x = (+-sqrt(-3) - 1) / 2
//
// [1] https://bitcointalk.org/index.php?topic=3238.msg45565#msg45565
// [2] https://crypto.stackexchange.com/a/22739
// [3] https://bitcoin.stackexchange.com/a/35872
// [4] https://github.com/halfinney/bitcoin/commit/dc411b5
// [5] https://en.wikipedia.org/wiki/Cube_root_of_unity
// [6] https://en.wikipedia.org/wiki/Splitting_field#Cubic_example
// [7] http://mathworld.wolfram.com/SplittingField.html
const red = num === this.p ? this.red : BN.mont(num);
const two = new BN(2).toRed(red);
const three = new BN(3).toRed(red);
const i2 = two.redInvert();
// S1 = sqrt(-3) / 2
const s1 = three.redNeg().redSqrt().redMul(i2);
// S2 = -S1
const s2 = s1.redNeg();
// R1 = S1 - 1 / 2
const r1 = s1.redSub(i2).fromRed();
// R2 = S2 - 1 / 2
const r2 = s2.redSub(i2).fromRed();
return [r1, r2].sort(BN.cmp);
}
_getEndoBasis(lambda) {
// Compute endomorphic basis.
//
// This essentially computes Cornacchia's algorithm
// for solving x^2 + d * y^2 = m (d = lambda, m = order).
//
// https://en.wikipedia.org/wiki/Cornacchia%27s_algorithm
//
// [GECC] Algorithm 3.74, Page 127, Section 3.5.
// [GLV] Page 196, Section 4 (Decomposing K).
//
// Balanced length-two representation of a multiplier.
//
// 1. Run the extended euclidean algorithm with inputs n
// and lambda. The algorithm produces a sequence of
// equations si*n + ti*lam = ri where s0=1, t0=0,
// r0=n, s1=0, t1=1, r1=lam, and the remainders ri
// and are non-negative and strictly decreasing. Let
// l be the greatest index for which rl >= sqrt(n).
const [rl, tl, rl1, tl1, rl2, tl2] = this._egcdSqrt(lambda);
// 2. Set (a1, b1) <- (rl+1, -tl+1).
const a1 = rl1;
const b1 = tl1.neg();
// 3. If (rl^2 + tl^2) <= (rl+2^2 + tl+2^2)
// then set (a2, b2) <- (rl, -tl).
// else set (a2, b2) <- (rl+2, -tl+2).
const lhs = rl.sqr().iadd(tl.sqr());
const rhs = rl2.sqr().iadd(tl2.sqr());
let a2, b2;
if (lhs.cmp(rhs) <= 0) {
a2 = rl;
b2 = tl.neg();
} else {
a2 = rl2;
b2 = tl2.neg();
}
return [
new Vector(a1, b1),
new Vector(a2, b2)
];
}
_egcdSqrt(lambda) {
// Extended Euclidean algorithm for integers.
//
// [GECC] Algorithm 2.19, Page 40, Section 2.2.
// [GLV] Page 196, Section 4 (Decomposing K).
assert(lambda instanceof BN);
assert(!lambda.red);
assert(lambda.sign() > 0);
assert(this.n.sign() > 0);
// Note that we insert the approximate square
// root checks as described in algorithm 3.74.
//
// Algorithm 2.19 is defined as:
//
// 1. u <- a
// v <- b
//
// 2. x1 <- 1
// y1 <- 0
// x2 <- 0
// y2 <- 1
//
// 3. while u != 0 do
//
// 3.1. q <- floor(v / u)
// r <- v - q * u
// x <- x2 - q * x1
// y <- y2 - q * y1
//
// 3.2. v <- u
// u <- r
// x2 <- x1
// x1 <- x
// y2 <- y1
// y1 <- y
//
// 4. d <- v
// x <- x2
// y <- y2
//
// 5. Return (d, x, y).
// Start with an approximate square root of n.
const sqrtn = this.n.ushrn(this.n.bitLength() >>> 1);
let u = lambda; // r1
let v = this.n.clone(); // r0
let x1 = new BN(1); // t1
let y1 = new BN(0); // t0
let x2 = new BN(0); // s1
let y2 = new BN(1); // s0
// All vectors are roots of: a + b * lambda = 0 (mod n).
let rl, tl;
// First vector.
let rl1, tl1;
// Inner.
let i = 0;
let j = 0;
let p;
// Compute EGCD.
while (!u.isZero() && i < 2) {
const q = v.quo(u);
const r = v.sub(q.mul(u));
const x = x2.sub(q.mul(x1));
const y = y2.sub(q.mul(y1));
// Check for r < sqrt(n).
if (j === 0 && r.cmp(sqrtn) < 0) {
rl = p;
tl = x1;
rl1 = r;
tl1 = x;
j = 1; // 1 more round.
}
p = r;
v = u;
u = r;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
i += j;
}
// Should never happen.
assert(j !== 0, 'Could not find r < sqrt(n).');
// Second vector.
const rl2 = x2;
const tl2 = x1;
return [
rl,
tl,
rl1,
tl1,
rl2,
tl2
];
}
_getEndoPrecomp(basis) {
// Precompute `g1` and `g2` to avoid round division.
//
// [JCEN12] Page 5, Section 4.3.
//
// Computation:
//
// d = a1 * b2 - b1 * a2
// t = ceil(log2(d+1)) + p
// g1 = round((2^t * b2) / d)
// g2 = round((2^t * b1) / d)
//
// Where:
//
// `p` is the number of precision bits.
// `d` is equal to `n` (the curve order).
//
// The paper above uses 2 as the value of `p`,
// whereas libsecp256k1 uses 128 (total=384).
//
// We pick precision for `g1` and `g2` such that:
//
// abs(g1) < n
// abs(g2) < n
//
// This ensures maximum precision for the constants
// while also ensuring they fit into a fixed number
// of scalar limbs in more optimized implementations.
//
// Furthermore, we attempt to align to a limb width
// of 64 bits. This allows us to optimize the shift,
// a la libsecp256k1[1].
//
// [1] https://github.com/bitcoin-core/secp256k1/pull/822
assert(Array.isArray(basis));
assert(basis.length === 2);
assert(basis[0] instanceof Vector);
assert(basis[1] instanceof Vector);
const [v1, v2] = basis;
const d = v1.a.mul(v2.b).isub(v1.b.mul(v2.a));
const bits = d.bitLength();
const align = bits >= 160;
assert(d.eq(this.n));
// Start with a rough estimate.
let shift = bits + Math.ceil(bits / 2) + 1;
let g1, g2;
if (align)
shift -= shift & 63;
while (shift > bits) {
g1 = v2.b.ushln(shift).divRound(d);
g2 = v1.b.ushln(shift).divRound(d);
if (g1.ucmp(d) < 0 && g2.ucmp(d) < 0)
break;
if (align)
shift -= 64;
else
shift -= 1;
}
if (shift <= bits)
throw new Error('Could not calculate g1 and g2.');
return [shift, g1, g2];
}
_endoSplit(k) {
// Balanced length-two representation of a multiplier.
//
// [GECC] Algorithm 3.74, Page 127, Section 3.5.
//
// Also note that it is possible to precompute[1]
// values in order to avoid the division[2][3][4].
//
// This involves precomputing `g1` and `g2 (see
// above). `c1` and `c2` can then be computed as
// follows:
//
// t = ceil(log2(n+1)) + p
// c1 = (k * g1) >> t
// c2 = -((k * g2) >> t)
//
// Where `>>` is an _unsigned_ right shift. Also
// note that the last bit discarded in the shift
// must be stored. If it is 1, then add 1 to the
// scalar (absolute addition).
//
// It's worth noting that libsecp256k1 uses a
// different calculation along the lines of:
//
// t = ceil(log2(n+1)) + p
// c1 = ((k * g1) >> t) * -b1
// c2 = ((k * -g2) >> t) * -b2
// k2 = c1 + c2
// k1 = k2 * -lambda + k
//
// So, in the future, we can consider changing
// step 4 to:
//
// 4. Compute c1 = (k * g1) >> t
// and c2 = -((k * g2) >> t).
//
// const [shift, g1, g2] = this.endo.pre;
// const c1 = k.mulShift(g1, shift);
// const c2 = k.mulShift(g2, shift).ineg();
//
// Once we're brave enough, that is.
//
// [1] [JCEN12] Page 5, Section 4.3.
// [2] https://github.com/bitcoin-core/secp256k1/blob/0b70241/src/scalar_impl.h#L259
// [3] https://github.com/bitcoin-core/secp256k1/pull/21
// [4] https://github.com/bitcoin-core/secp256k1/pull/127
assert(k instanceof BN);
assert(!k.red);
assert(!this.n.isZero());
const [v1, v2] = this.endo.basis;
// 4. Compute c1 = round(b2 * k / n)
// and c2 = round(-b1 * k / n).
const c1 = v2.b.mul(k).divRound(this.n);
const c2 = v1.b.neg().mul(k).divRound(this.n);
// 5. Compute k1 = k - c1 * a1 - c2 * a2
// and k2 = -c1 * b1 - c2 * b2.
const p1 = c1.mul(v1.a);
const p2 = c2.mul(v2.a);
const q1 = c1.ineg().mul(v1.b);
const q2 = c2.mul(v2.b);
// Calculate answer.
const k1 = k.sub(p1).isub(p2);
const k2 = q1.isub(q2);
// 6. Return (k1, k2).
return [k1, k2];
}
_endoBeta(point) {
assert(point instanceof ShortPoint);
return [point, point._getBeta()];
}
_endoWnafMulAdd(points, coeffs) {
// Point multiplication with efficiently computable endomorphisms.
//
// [GECC] Algorithm 3.77, Page 129, Section 3.5.
// [GLV] Page 193, Section 3 (Using Efficient Endomorphisms).
//
// Note it may be possible to do this 4-dimensionally [4GLV].
assert(Array.isArray(points));
assert(Array.isArray(coeffs));
assert(points.length === coeffs.length);
assert(this.endo != null);
const len = points.length;
const npoints = new Array(len * 2);
const ncoeffs = new Array(len * 2);
for (let i = 0; i < len; i++) {
const [p1, p2] = this._endoBeta(points[i]);
const [k1, k2] = this._endoSplit(coeffs[i]);
npoints[i * 2 + 0] = p1;
ncoeffs[i * 2 + 0] = k1;
npoints[i * 2 + 1] = p2;
ncoeffs[i * 2 + 1] = k2;
}
return this._wnafMulAdd(5, npoints, ncoeffs);
}
_sswu(u) {
// Simplified Shallue-Woestijne-Ulas Method.
//
// Distribution: 3/8.
//
// [SSWU1] Page 15-16, Section 7. Appendix G.
// [SSWU2] Page 5, Theorem 2.3.
// [H2EC] "Simplified Shallue-van de Woestijne-Ulas Method".
//
// Assumptions:
//
// - a != 0, b != 0.
// - Let z be a non-square in F(p).
// - z != -1.
// - The polynomial g(x) - z is irreducible over F(p).
// - g(b / (z * a)) is square in F(p).
// - u != 0, u != +-sqrt(-1 / z).
//
// Map:
//
// g(x) = x^3 + a * x + b
// t1 = 1 / (z^2 * u^4 + z * u^2)
// x1 = (-b / a) * (1 + t1)
// x1 = b / (z * a), if t1 = 0
// x2 = z * u^2 * x1
// x = x1, if g(x1) is square
// = x2, otherwise
// y = sign(u) * abs(sqrt(g(x)))
const {b, z, ai, zi, one} = this;
const z2 = z.redSqr();
const ba = b.redNeg().redMul(ai);
const bza = b.redMul(zi).redMul(ai);
const u2 = u.redSqr();
const u4 = u2.redSqr();
const t0 = z2.redMul(u4).redIAdd(z.redMul(u2));
const t1 = t0.isZero() ? t0 : t0.redInvert();
const x1 = t1.isZero() ? bza : ba.redMul(one.redAdd(t1));
const x2 = z.redMul(u2).redMul(x1);
const y1 = this.solveY2(x1);
const y2 = this.solveY2(x2);
const alpha = y1.redIsSquare() | 0;
const x = [x1, x2][alpha ^ 1];
const y = [y1, y2][alpha ^ 1].redSqrt();
if (y.redIsOdd() !== u.redIsOdd())
y.redINeg();
return this.point(x, y);
}
_sswui(p, hint) {
// Inverting the Map (Simplified Shallue-Woestijne-Ulas).
//
// Assumptions:
//
// - a^2 * x^2 - 2 * a * b * x - 3 * b^2 is square in F(p).
// - If r < 3 then x != -b / a.
//
// Unlike SVDW, the preimages here are evenly
// distributed (more or less). SSWU covers ~3/8
// of the curve points. Each preimage has a 1/2
// chance of mapping to either x1 or x2.
//
// Assuming the point is within that set, each
// point has a 1/4 chance of inverting to any
// of the preimages. This means we can simply
// randomly select a preimage if one exists.
//
// However, the [SVDW2] sampling method seems
// slighly faster in practice for [SQUARED].
//
// Map:
//
// c = sqrt(a^2 * x^2 - 2 * a * b * x - 3 * b^2)
// u1 = -(a * x + b - c) / (2 * (a * x + b) * z)
// u2 = -(a * x + b + c) / (2 * (a * x + b) * z)
// u3 = -(a * x + b - c) / (2 * b * z)
// u4 = -(a * x + b + c) / (2 * b * z)
// r = random integer in [1,4]
// u = sign(y) * abs(sqrt(ur))
const {a, b, z} = this;
const {x, y} = p;
const r = hint & 3;
const a2x2 = a.redSqr().redMul(x.redSqr());
const abx2 = a.redMul(b).redMul(x).redIMuln(2);
const b23 = b.redSqr().redMuln(3);
const axb = a.redMul(x).redIAdd(b);
const c = a2x2.redISub(abx2).redISub(b23).redSqrt();
const n0 = axb.redSub(c).redINeg();
const n1 = axb.redAdd(c).redINeg();
const d0 = axb.redMul(z).redIMuln(2);
const d1 = b.redMul(z).redIMuln(2);
const n = [n0, n1][r & 1]; // r = 1 or 3
const d = [d0, d1][r >>> 1]; // r = 2 or 3
const u = n.redDivSqrt(d);
if (u.redIsOdd() !== y.redIsOdd())
u.redINeg();
return u;
}
_svdwf(u) {
// Shallue-van de Woestijne Method.
//
// Distribution: 9/16.
//
// [SVDW1] Section 5.
// [SVDW2] Page 8, Section 3.
// Page 15, Section 6, Algorithm 1.
// [H2EC] "Shallue-van de Woestijne Method".
//
// Assumptions:
//
// - p = 1 (mod 3).
// - a = 0, b != 0.
// - Let z be a unique element in F(p).
// - g((sqrt(-3 * z^2) - z) / 2) is square in F(p).
// - u != 0, u != +-sqrt(-g(z)).
//
// Map:
//
// g(x) = x^3 + b
// c = sqrt(-3 * z^2)
// t1 = u^2 + g(z)
// t2 = 1 / (u^2 * t1)
// t3 = u^4 * t2 * c
// x1 = (c - z) / 2 - t3
// x2 = t3 - (c + z) / 2
// x3 = z - t1^3 * t2 / (3 * z^2)
// x = x1, if g(x1) is square
// = x2, if g(x2) is square
// = x3, otherwise
// y = sign(u) * abs(sqrt(g(x)))
const {c, z, zi, i2, i3} = this;
const gz = this.solveY2(z);
const z3 = i3.redMul(zi.redSqr());
const u2 = u.redSqr();
const u4 = u2.redSqr();
const t1 = u2.redAdd(gz);
const u2t1 = u2.redMul(t1);
const t2 = u2t1.isZero() ? u2t1 : u2t1.redInvert();
const t3 = u4.redMul(t2).redMul(c);
const t4 = t1.redSqr().redMul(t1);
const x1 = c.redSub(z).redMul(i2).redISub(t3);
const x2 = t3.redSub(c.redAdd(z).redMul(i2));
const x3 = z.redSub(t4.redMul(t2).redMul(z3));
const y1 = this.solveY2(x1);
const y2 = this.solveY2(x2);
const y3 = this.solveY2(x3);
const alpha = y1.redJacobi() | 1;
const beta = y2.redJacobi() | 1;
const i = mod((alpha - 1) * beta, 3);
const x = [x1, x2, x3][i];
const y = [y1, y2, y3][i];
return [x, y];
}
_svdw(u) {
const [x, yy] = this._svdwf(u);
const y = yy.redSqrt();
if (y.redIsOdd() !== u.redIsOdd())
y.redINeg();
return this.point(x, y);
}
_svdwi(p, hint) {
// Inverting the Map (Shallue-van de Woestijne).
//
// [SQUARED] Algorithm 1, Page 8, Section 3.3.
// [SVDW2] Page 12, Section 5.
// [SVDW3] "Inverting the map".
//
// Assumptions:
//
// - If r = 1 then x != -(c + z) / 2.
// - If r = 2 then x != (c - z) / 2.
// - If r > 2 then (t0 - t1 + t2) is square in F(p).
// - f(f^-1(x)) = x where f is the map function.
//
// We use the sampling method from [SVDW2],
// _not_ [SQUARED]. This seems to have a
// better distribution in practice.
//
// Note that [SVDW3] also appears to be
// incorrect in terms of distribution.
//
// The distribution of f(u), assuming u is
// random, is (1/2, 1/4, 1/4).
//
// To mirror this, f^-1(x) should simply
// pick (1/2, 1/4, 1/8, 1/8).
//
// To anyone running the forward map, our
// strings will appear to be random.
//
// Map:
//
// g(x) = x^3 + b
// c = sqrt(-3 * z^2)
// t0 = 9 * (x^2 * z^2 + z^4)
// t1 = 18 * x * z^3
// t2 = 12 * g(z) * (x - z)
// t3 = sqrt(t0 - t1 + t2)
// t4 = t3 * z
// u1 = g(z) * (c - 2 * x - z) / (c + 2 * x + z)
// u2 = g(z) * (c + 2 * x + z) / (c - 2 * x - z)
// u3 = (3 * (z^3 - x * z^2) - 2 * g(z) + t4) / 2
// u4 = (3 * (z^3 - x * z^2) - 2 * g(z) - t4) / 2
// r = random integer in [1,4]
// u = sign(y) * abs(sqrt(ur))
const {b, c, z, zero, two} = this;
const {x, y} = p;
const r = hint & 3;
const z2 = z.redSqr();
const z3 = z2.redMul(z);
const z4 = z2.redSqr();
const gz = z3.redAdd(b);
const gz2 = gz.redMuln(2);
const xx = x.redSqr();
const x2z = x.redMuln(2).redIAdd(z);
const xz2 = x.redMul(z2);
const c0 = c.redSub(x2z);
const c1 = c.redAdd(x2z);
const t0 = xx.redMul(z2).redIAdd(z4).redIMuln(9);
const t1 = x.redMul(z3).redIMuln(18);
const t2 = gz.redMul(x.redSub(z)).redIMuln(12);
const t3 = r >= 2 ? t0.redISub(t1).redIAdd(t2).redSqrt() : zero;
const t4 = t3.redMul(z);
const t5 = z3.redISub(xz2).redIMuln(3).redISub(gz2);
const n0 = gz.redMul(c0);
const n1 = gz.redMul(c1);
const n2 = t5.redAdd(t4);
const n3 = t5.redSub(t4);
const d2 = two;
const n = [n0, n1, n2, n3][r];
const d = [c1, c0, d2, d2][r];
const u = n.redDivSqrt(d);
const [x0] = this._svdwf(u);
if (!x0.eq(x))
throw new Error('Invalid point.');
if (u.redIsOdd() !== y.redIsOdd())
u.redINeg();
return u;
}
isElliptic() {
const {a, b} = this;
const a2 = a.redSqr();
const a3 = a2.redMul(a);
const b2 = b.redSqr();
const d = b2.redMuln(27).redIAdd(a3.redMuln(4));
// 4 * a^3 + 27 * b^2 != 0
return !d.isZero();
}
jinv() {
// [ARITH1] Page 71, Section 4.4.
// http://mathworld.wolfram.com/j-Invariant.html
const {a, b} = this;
const a2 = a.redSqr();
const a3 = a2.redMul(a);
const b2 = b.redSqr();
const t0 = a3.redMuln(4);
const lhs = t0.redMuln(1728);
const rhs = b2.redMuln(27).redIAdd(t0);
if (rhs.isZero())
throw new Error('Curve is not elliptic.');
// (1728 * 4 * a^3) / (4 * a^3 + 27 * b^2)
return lhs.redDiv(rhs).fromRed();
}
point(x, y) {
return new ShortPoint(this, x, y);
}
jpoint(x, y, z) {
return new JPoint(this, x, y, z);
}
solveX(y) {
assert(y instanceof BN);
if (!this.a.isZero())
throw new Error('Not implemented.');
// x^3 = y^2 - b
const y2 = y.redSqr();
const x3 = y2.redSub(this.b);
return cubeRoots(x3);
}
solveY2(x) {
// [GECC] Page 89, Section 3.2.2.
// https://hyperelliptic.org/EFD/g1p/auto-shortw.html
assert(x instanceof BN);
// y^2 = x^3 + a * x + b
const x3 = x.redSqr().redMul(x);
const y2 = x3.redIAdd(this.b);
if (!this.zeroA) {
// Save some cycles for a = -3.
if (this.threeA)
y2.redIAdd(x.redMuln(-3));
else
y2.redIAdd(this.a.redMul(x));
}
return y2;
}
validate(point) {
assert(point instanceof ShortPoint);
if (point.inf)
return true;
const {x, y} = point;
const y2 = this.solveY2(x);
return y.redSqr().eq(y2);
}
pointFromX(x, sign = null) {
assert(x instanceof BN);
assert(sign == null || typeof sign === 'boolean');
if (!x.red)
x = x.toRed(this.red);
const y = this.solveY(x);
if (sign != null) {
if (this.h.cmpn(1) > 0) {
if (y.isZero() && sign)
throw new Error('Invalid point.');
}
if (y.redIsOdd() !== sign)
y.redINeg();
}
return this.point(x, y);
}
pointFromY(y, index = 0) {
assert(y instanceof BN);
assert((index >>> 0) === index);
if (!y.red)
y = y.toRed(this.red);
const coords = this.solveX(y);
if (index >= coords.length)
throw new Error('Invalid X coordinate index.');
const x = coords[index];
return this.point(x, y);
}
isIsomorphic(curve) {
// [GECC] Page 84, Section 3.1.5.
// [ARITH1] Page 286, Section 13.2.3.c.
assert(curve instanceof Curve);
if (!curve.p.eq(this.p))
return false;
let u2, u3;
try {
[u2, u3] = this._scale(curve);
} catch (e) {
return false;
}
// E(a,b) <-> E(au^4,bu^6)
if (curve.type === 'short') {
// a' = a * u^4, b' = b * u^6
const a = this.field(curve.a).redMul(u2.redSqr());
const b = this.field(curve.b).redMul(u3.redSqr());
return this.a.eq(a) && this.b.eq(b);
}
// E(a,b) <-> M(A,B)
if (curve.type === 'mont') {
// (A / (3 * B))^3 + a * (A / (3 * B)) + b = 0
const {a3, bi} = curve;
const x = this.field(a3.redMul(bi)).redMul(u2);
const y2 = this.solveY2(x);
return y2.isZero();
}
// E(a,b) <-> E(a,d)
if (curve.type === 'edwards') {
// ((a' + d') / 6)^3 + a * ((a' + d') / 6) + b = 0
const x = this.field(curve.ad6).redMul(u2);
const y2 = this.solveY2(x);
return y2.isZero();
}
return false;
}
isIsogenous(curve) {
assert(curve instanceof Curve);
return false;
}
pointFromShort(point) {
// [GECC] Page 84, Section 3.1.5.
// [ALT] Appendix F.3 (Isomorphic Mapping between Weierstrass Curves).
assert(point instanceof ShortPoint);
if (this.isIsomorphic(point.curve)) {
// Isomorphic maps for E(a,b)<->E(au^4,bu^6):
//
// x' = x * u^2
// y' = y * u^3
//
// Where a * u^4 = a' and b * u^6 = b'.
if (point.isInfinity())
return this.point();
const [u2, u3] = this._scale(point.curve);
const x = this.field(point.x);
const y = this.field(point.y);
const nx = x.redMul(u2);
const ny = y.redMul(u3);
return this.point(nx, ny);
}
throw new Error('Not implemented.');
}
pointFromMont(point) {
// [ALT] Appendix E.2 (Switching between Alternative Representations).
// [MONT2] "Equivalence with Weierstrass curves"
assert(point instanceof MontPoint);
if (this.isIsomorphic(point.curve)) {
// Equivalence for M(A,B)->E(a,b):
//
// x = (u + A / 3) / B
// y = v / B
//
// Undefined if ((u^3 + A * u^2 + u) / B) is not square.
if (point.isInfinity())
return this.point();
const {a3, bi} = point.curve;
const [u2, u3] = this._scale(point.curve);
const nx = point.x.redAdd(a3).redMul(bi);
const ny = point.y.redMul(bi);
return this.point(this.field(nx).redMul(u2),
this.field(ny).redMul(u3));
}
throw new Error('Not implemented.');
}
pointFromEdwards(point) {
// [TWISTEQ] Section 2.
assert(point instanceof EdwardsPoint);
if (this.isIsomorphic(point.curve)) {
// Equivalence for E(a,d)->E(a',b'):
//
// x' = ((5 * d - a) * y + d - 5 * a) / (12 * (y - 1))
// y' = (d - a) * (y + 1) / (4 * x * (y - 1))
//
// Undefined for x = 0 or y = 1.
//
// Exceptional Cases:
// - (0, 1) -> O
// - (0, -1) -> ((a + d) / 6, 0)
//
// Unexceptional Cases:
// - (sqrt(1 / a), 0) -> ((5 * a - d) / 12, (a - d) / 4 * sqrt(a))
const {a, d, ad6} = point.curve;
const [u2, u3] = this._scale(point.curve);
if (point.isInfinity())
return this.point();
if (point.x.isZero()) {
const x = this.field(ad6).redMul(u2);
return this.point(x, this.zero);
}
const {x, y, z} = point;
const a5 = a.redMuln(5);
const d5 = d.redMuln(5);
const dma = d.redSub(a);
const d5a = d5.redSub(a);
const da5 = d.redSub(a5);
const ypz = y.redAdd(z);
const ymz = y.redSub(z);
const xx = d5a.redMul(y).redIAdd(da5.redMul(z));
const xz = ymz.redMuln(12);
const yy = dma.redMul(ypz).redMul(z);
const yz = ymz.redMul(x).redIMuln(4);
return this.cpoint(this.field(xx).redMul(u2),
this.field(xz),
this.field(yy).redMul(u3),
this.field(yz));
}
throw new Error('Not implemented.');
}
pointFromUniform(u) {
assert(u instanceof BN);
// z = 0 or b = 0
if (this.z.isZero() || this.b.isZero())
throw new Error('Not implemented.');
// a != 0, b != 0
if (!this.a.isZero())
return this._sswu(u);
// p = 1 mod 3, a = 0, b != 0
if (!this.c.isZero())
return this._svdw(u);
throw new Error('Not implemented.');
}
pointToUniform(p, hint) {
// Convert a short weierstrass point to a field
// element by inverting either the SSWU or SVDW
// map.
//
// Hint Layout:
//
// [00000000] [0000] [0000]
// | | |
// | | +-- preimage index
// | +--- subgroup
// +-- bits to OR with uniform bytes
assert(p instanceof ShortPoint);
assert((hint >>> 0) === hint);
// z = 0 or b = 0
if (this.z.isZero() || this.b.isZero())
throw new Error('Not implemented.');
// P = O
if (p.isInfinity())
throw new Error('Invalid point.');
// Add a random torsion component.
const i = ((hint >>> 4) & 15) % this.torsion.length;
const q = p.add(this.torsion[i]);
return wrapErrors(() => {
// a != 0, b != 0
if (!this.a.isZero())
return this._sswui(q, hint);
// p = 1 mod 3, a = 0, b != 0
if (!this.c.isZero())
return this._svdwi(q, hint);
throw new Error('Not implemented.');
});
}
mulAll(points, coeffs) {
return super.mulAll(points, coeffs).toP();
}
affinizeAll(points) {
const out = this.normalizeAll(points);
for (let i = 0; i < out.length; i++)
out[i] = out[i].toP();
return out;
}
decodePoint(bytes) {
return ShortPoint.decode(this, bytes);
}
encodeX(point) {
assert(point instanceof Point);
return point.encodeX();
}
decodeEven(bytes) {
return ShortPoint.decodeEven(this, bytes);
}
decodeSquare(bytes) {
return ShortPoint.decodeSquare(this, bytes);
}
toShort(a0, odd, sign = null) {
const [a, b] = this._short(a0, odd);
const curve = new ShortCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
b: b,
n: this.n,
h: this.h
});
if (sign != null) {
const [, u3] = curve._scale(this);
if (u3.redIsOdd() !== sign)
u3.redINeg();
}
if (!this.g.isInfinity())
curve.g = curve.pointFromShort(this.g);
for (let i = 0; i < this.h.word(0); i++)
curve.torsion[i] = curve.pointFromShort(this.torsion[i]);
return curve;
}
toMont(b0, odd, sign = null) {
const [a, b] = this._mont(b0, odd);
const curve = new MontCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
b: b,
n: this.n,
h: this.h
});
if (sign != null) {
const [, u3] = this._scale(curve);
if (u3.redIsOdd() !== sign)
u3.redINeg();
}
if (!this.g.isInfinity())
curve.g = curve.pointFromShort(this.g);
for (let i = 0; i < this.h.word(0); i++)
curve.torsion[i] = curve.pointFromShort(this.torsion[i]);
return curve;
}
toEdwards(a0, odd, sign = null) {
const [a, d] = this._edwards(a0, odd);
const curve = new EdwardsCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
d: d,
n: this.n,
h: this.h
});
if (sign != null) {
const [, u3] = this._scale(curve);
if (u3.redIsOdd() !== sign)
u3.redINeg();
}
if (!this.g.isInfinity()) {
curve.g = curve.pointFromShort(this.g);
curve.g.normalize();
}
if (curve.isComplete()) {
for (let i = 0; i < this.h.word(0); i++) {
curve.torsion[i] = curve.pointFromShort(this.torsion[i]);
curve.torsion[i].normalize();
}
}
return curve;
}
pointFromJSON(json) {
return ShortPoint.fromJSON(this, json);
}
toJSON(pre) {
const json = super.toJSON(pre);
json.a = this.a.fromRed().toJSON();
json.b = this.b.fromRed().toJSON();
if (!this.c.isZero())
json.c = this.c.fromRed().toJSON();
return json;
}
}
/**
* ShortPoint
*/
class ShortPoint extends Point {
constructor(curve, x, y) {
assert(curve instanceof ShortCurve);
super(curve, types.AFFINE);
this.x = this.curve.zero;
this.y = this.curve.zero;
this.inf = true;
if (x != null)
this._init(x, y);
}
_init(x, y) {
assert(x instanceof BN);
assert(y instanceof BN);
this.x = x;
this.y = y;
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.y.red)
this.y = this.y.toRed(this.curve.red);
this.inf = false;
}
_getBeta() {
if (!this.curve.endo)
return null;
if (this.pre && this.pre.beta)
return this.pre.beta;
// Augment the point with our beta value.
// This is the counterpart to `k2` after
// the endomorphism split of `k`.
//
// Note that if we have precomputation,
// we have to clone and update all of the
// precomputed points below.
const xb = this.x.redMul(this.curve.endo.beta);
const beta = this.curve.point(xb, this.y);
if (this.pre) {
beta.pre = this.pre.map((point) => {
const xb = point.x.redMul(this.curve.endo.beta);
return this.curve.point(xb, point.y);
});
this.pre.beta = beta;
}
return beta;
}
_getJNAF(point) {
assert(point instanceof ShortPoint);
if (this.inf || point.inf)
return super._getJNAF(point);
// Create comb for JSF.
const comb = [
this, // 1
null, // 3
null, // 5
point // 7
];
// Try to avoid Jacobian points, if possible.
if (this.y.eq(point.y)) {
comb[1] = this.add(point);
comb[2] = this.toJ().sub(point);
} else if (this.y.eq(point.y.redNeg())) {
comb[1] = this.toJ().add(point);
comb[2] = this.sub(point);
} else {
comb[1] = this.toJ().add(point);
comb[2] = this.toJ().sub(point);
}
return comb;
}
clone() {
if (this.inf)
return this.curve.point();
return this.curve.point(this.x, this.y);
}
scale(a) {
return this.toJ().scale(a);
}
neg() {
// P = O
if (this.inf)
return this;
// -(X1, Y1) = (X1, -Y1)
return this.curve.point(this.x, this.y.redNeg());
}
add(p) {
// [GECC] Page 80, Section 3.1.2.
//
// Addition Law:
//
// l = (y1 - y2) / (x1 - x2)
// x3 = l^2 - x1 - x2
// y3 = l * (x1 - x3) - y1
//
// 1I + 2M + 1S + 6A
assert(p instanceof ShortPoint);
// O + P = P
if (this.inf)
return p;
// P + O = P
if (p.inf)
return this;
// P + P, P + -P
if (this.x.eq(p.x)) {
// P + -P = O
if (!this.y.eq(p.y))
return this.curve.point();
// P + P = 2P
return this.dbl();
}
// X1 != X2, Y1 = Y2
if (this.y.eq(p.y)) {
// X3 = -X1 - X2
const nx = this.x.redNeg().redISub(p.x);
// Y3 = -Y1
const ny = this.y.redNeg();
// Skip the inverse.
return this.curve.point(nx, ny);
}
// H = X1 - X2
const h = this.x.redSub(p.x);
// R = Y1 - Y2
const r = this.y.redSub(p.y);
// L = R / H
const l = r.redDiv(h);
// X3 = L^2 - X1 - X2
const nx = l.redSqr().redISub(this.x).redISub(p.x);
// Y3 = L * (X1 - X3) - Y1
const ny = l.redMul(this.x.redSub(nx)).redISub(this.y);
return this.curve.point(nx, ny);
}
dbl() {
// [GECC] Page 80, Section 3.1.2.
//
// Addition Law (doubling):
//
// l = (3 * x1^2 + a) / (2 * y1)
// x3 = l^2 - 2 * x1
// y3 = l * (x1 - x3) - y1
//
// 1I + 2M + 2S + 3A + 2*2 + 1*3
// P = O
if (this.inf)
return this;
// Y1 = 0
if (this.y.isZero())
return this.curve.point();
// XX = X1^2
const xx = this.x.redSqr();
// M = 3 * XX + a
const m = xx.redIMuln(3).redIAdd(this.curve.a);
// Z = 2 * Y1
const z = this.y.redMuln(2);
// L = M / Z
const l = m.redDiv(z);
// X3 = L^2 - 2 * X1
const nx = l.redSqr().redISub(this.x).redISub(this.x);
// Y3 = L * (X1 - X3) - Y1
const ny = l.redMul(this.x.redSub(nx)).redISub(this.y);
return this.curve.point(nx, ny);
}
dblp(pow) {
return this.toJ().dblp(pow).toP();
}
getX() {
if (this.inf)
throw new Error('Invalid point.');
return this.x.fromRed();
}
getY() {
if (this.inf)
throw new Error('Invalid point.');
return this.y.fromRed();
}
eq(p) {
assert(p instanceof ShortPoint);
// P = Q
if (this === p)
return true;
// P = O
if (this.inf)
return p.inf;
// Q = O
if (p.inf)
return false;
// X1 = X2, Y1 = Y2
return this.x.eq(p.x)
&& this.y.eq(p.y);
}
cmp(point) {
assert(point instanceof ShortPoint);
if (this.inf && !point.inf)
return -1;
if (!this.inf && point.inf)
return 1;
if (this.inf && point.inf)
return 0;
return this.order().cmp(point.order())
|| this.getX().cmp(point.getX())
|| this.getY().cmp(point.getY());
}
isInfinity() {
// Infinity cannot be represented in
// the affine space, except by a flag.
return this.inf;
}
isOrder2() {
if (this.inf)
return false;
return this.y.isZero();
}
isOdd() {
if (this.inf)
return false;
return this.y.redIsOdd();
}
isEven() {
if (this.inf)
return false;
return this.y.redIsEven();
}
isSquare() {
if (this.inf)
return false;
return this.y.redJacobi() !== -1;
}
eqX(x) {
assert(x instanceof BN);
assert(!x.red);
if (this.inf)
return false;
return this.getX().eq(x);
}
eqR(x) {
assert(x instanceof BN);
assert(!x.red);
assert(!this.curve.n.isZero());
if (this.inf)
return false;
return this.getX().imod(this.curve.n).eq(x);
}
mul(k) {
return super.mul(k).toP();
}
muln(k) {
return super.muln(k).toP();
}
mulBlind(k, rng) {
return super.mulBlind(k, rng).toP();
}
mulAdd(k1, p2, k2) {
return super.mulAdd(k1, p2, k2).toP();
}
mulH() {
return super.mulH().toP();
}
div(k) {
return super.div(k).toP();
}
divn(k) {
return super.divn(k).toP();
}
divH() {
return super.divH().toP();
}
toP() {
return this;
}
toJ() {
// (X3, Y3, Z3) = (1, 1, 0)
if (this.inf)
return this.curve.jpoint();
// (X3, Y3, Z3) = (X1, Y1, 1)
return this.curve.jpoint(this.x, this.y, this.curve.one);
}
encode(compact) {
// [SEC1] Page 10, Section 2.3.3.
if (compact == null)
compact = true;
assert(typeof compact === 'boolean');
const {fieldSize} = this.curve;
// We do not serialize points at infinity.
if (this.inf)
throw new Error('Invalid point.');
// Compressed form (0x02 = even, 0x03 = odd).
if (compact) {
const p = Buffer.alloc(1 + fieldSize);
const x = this.curve.encodeField(this.getX());
p[0] = 0x02 | this.y.redIsOdd();
x.copy(p, 1);
return p;
}
// Uncompressed form (0x04).
const p = Buffer.alloc(1 + fieldSize * 2);
const x = this.curve.encodeField(this.getX());
const y = this.curve.encodeField(this.getY());
p[0] = 0x04;
x.copy(p, 1);
y.copy(p, 1 + fieldSize);
return p;
}
static decode(curve, bytes) {
// [SEC1] Page 11, Section 2.3.4.
assert(curve instanceof ShortCurve);
assert(Buffer.isBuffer(bytes));
const len = curve.fieldSize;
if (bytes.length < 1 + len)
throw new Error('Not a point.');
// Point forms:
//
// 0x00 -> Infinity (openssl, unsupported)
// 0x02 -> Compressed Even
// 0x03 -> Compressed Odd
// 0x04 -> Uncompressed
// 0x06 -> Hybrid Even (openssl)
// 0x07 -> Hybrid Odd (openssl)
//
// Note that openssl supports serializing points
// at infinity as {0}. We choose not to support it
// because it's strange and not terribly useful.
const form = bytes[0];
switch (form) {
case 0x02:
case 0x03: {
if (bytes.length !== 1 + len)
throw new Error('Invalid point size for compressed.');
const x = curve.decodeField(bytes.slice(1, 1 + len));
if (x.cmp(curve.p) >= 0)
throw new Error('Invalid point.');
const p = curve.pointFromX(x, form === 0x03);
assert(!p.isInfinity());
return p;
}
case 0x04:
case 0x06:
case 0x07: {
if (bytes.length !== 1 + len * 2)
throw new Error('Invalid point size for uncompressed.');
const x = curve.decodeField(bytes.slice(1, 1 + len));
const y = curve.decodeField(bytes.slice(1 + len, 1 + 2 * len));
// [GECC] Algorithm 4.3, Page 180, Section 4.
if (x.cmp(curve.p) >= 0 || y.cmp(curve.p) >= 0)
throw new Error('Invalid point.');
// OpenSSL hybrid encoding.
if (form !== 0x04 && form !== (0x06 | y.isOdd()))
throw new Error('Invalid hybrid encoding.');
const p = curve.point(x, y);
if (!p.validate())
throw new Error('Invalid point.');
assert(!p.isInfinity());
return p;
}
default: {
throw new Error('Unknown point format.');
}
}
}
encodeX() {
// [SCHNORR] "Specification".
// [BIP340] "Specification".
return this.curve.encodeField(this.getX());
}
static decodeEven(curve, bytes) {
// [BIP340] "Specification".
assert(curve instanceof ShortCurve);
const x = curve.decodeField(bytes);
if (x.cmp(curve.p) >= 0)
throw new Error('Invalid point.');
return curve.pointFromX(x, false);
}
static decodeSquare(curve, bytes) {
// [SCHNORR] "Specification".
assert(curve instanceof ShortCurve);
const x = curve.decodeField(bytes);
if (x.cmp(curve.p) >= 0)
throw new Error('Invalid point.');
return curve.pointFromX(x);
}
toJSON(pre) {
if (this.inf)
return [];
const x = this.getX().toJSON();
const y = this.getY().toJSON();
if (pre === true && this.pre)
return [x, y, this.pre.toJSON()];
return [x, y];
}
toPretty() {
if (this.inf)
return [];
const size = this.curve.fieldSize * 2;
const x = toPretty(this.getX(), size);
const y = toPretty(this.getY(), size);
return [x, y];
}
static fromJSON(curve, json) {
assert(curve instanceof ShortCurve);
assert(Array.isArray(json));
assert(json.length === 0
|| json.length === 2
|| json.length === 3);
if (json.length === 0)
return curve.point();
const x = BN.fromJSON(json[0]);
const y = BN.fromJSON(json[1]);
const point = curve.point(x, y);
if (json.length > 2 && json[2] != null)
point.pre = Precomp.fromJSON(point, json[2]);
return point;
}
[custom]() {
if (this.inf)
return '<ShortPoint: Infinity>';
return '<ShortPoint:'
+ ' x=' + this.x.fromRed().toString(16, 2)
+ ' y=' + this.y.fromRed().toString(16, 2)
+ '>';
}
}
/**
* JPoint
*/
class JPoint extends Point {
constructor(curve, x, y, z) {
assert(curve instanceof ShortCurve);
super(curve, types.JACOBIAN);
this.x = this.curve.one;
this.y = this.curve.one;
this.z = this.curve.zero;
this.zOne = false;
if (x != null)
this._init(x, y, z);
}
_init(x, y, z) {
assert(x instanceof BN);
assert(y instanceof BN);
assert(z == null || (z instanceof BN));
this.x = x;
this.y = y;
this.z = z || this.curve.one;
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.y.red)
this.y = this.y.toRed(this.curve.red);
if (!this.z.red)
this.z = this.z.toRed(this.curve.red);
this.zOne = this.z.eq(this.curve.one);
}
clone() {
return this.curve.jpoint(this.x, this.y, this.z);
}
validate() {
// [GECC] Example 3.20, Page 88, Section 3.
const {a, b} = this.curve;
// P = O
if (this.isInfinity())
return true;
// Z1 = 1
if (this.zOne)
return this.curve.validate(this.toP());
// y^2 = x^3 + a * x * z^4 + b * z^6
const lhs = this.y.redSqr();
const x3 = this.x.redSqr().redMul(this.x);
const z2 = this.z.redSqr();
const z4 = z2.redSqr();
const z6 = z4.redMul(z2);
const rhs = x3.redIAdd(b.redMul(z6));
if (!this.curve.zeroA) {
// Save some cycles for a = -3.
if (this.curve.threeA)
rhs.redIAdd(z4.redIMuln(-3).redMul(this.x));
else
rhs.redIAdd(a.redMul(z4).redMul(this.x));
}
return lhs.eq(rhs);
}
normalize() {
// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#scaling-z
// 1I + 3M + 1S
// Z = 1
if (this.zOne)
return this;
// P = O
if (this.isInfinity())
return this;
// A = 1 / Z1
const a = this.z.redInvert();
// AA = A^2
const aa = a.redSqr();
// X3 = X1 * AA
this.x = this.x.redMul(aa);
// Y3 = Y1 * AA * A
this.y = this.y.redMul(aa).redMul(a);
// Z3 = 1
this.z = this.curve.one;
this.zOne = true;
return this;
}
scale(a) {
assert(a instanceof BN);
// P = O
if (this.isInfinity())
return this.curve.jpoint();
// AA = A^2
const aa = a.redSqr();
// X3 = X1 * AA
const nx = this.x.redMul(aa);
// Y3 = Y1 * AA * A
const ny = this.y.redMul(aa).redMul(a);
// Z3 = Z1 * A
const nz = this.z.redMul(a);
return this.curve.jpoint(nx, ny, nz);
}
neg() {
// -(X1, Y1, Z1) = (X1, -Y1, Z1)
return this.curve.jpoint(this.x, this.y.redNeg(), this.z);
}
add(p) {
assert(p instanceof Point);
if (p.type === types.AFFINE)
return this._mixedAdd(p);
return this._add(p);
}
_add(p) {
assert(p instanceof JPoint);
// O + P = P
if (this.isInfinity())
return p;
// P + O = P
if (p.isInfinity())
return this;
// Z1 = 1
if (this.zOne)
return p._addJA(this);
// Z2 = 1
if (p.zOne)
return this._addJA(p);
return this._addJJ(p);
}
_mixedAdd(p) {
assert(p instanceof ShortPoint);
// O + P = P
if (this.isInfinity())
return p.toJ();
// P + O = P
if (p.isInfinity())
return this;
return this._addJA(p);
}
_addJJ(p) {
// No assumptions.
// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-1998-cmo-2
// 12M + 4S + 6A + 1*2 (implemented as: 12M + 4S + 7A)
// Z1Z1 = Z1^2
const z1z1 = this.z.redSqr();
// Z2Z2 = Z2^2
const z2z2 = p.z.redSqr();
// U1 = X1 * Z2Z2
const u1 = this.x.redMul(z2z2);
// U2 = X2 * Z1Z1
const u2 = p.x.redMul(z1z1);
// S1 = Y1 * Z2 * Z2Z2
const s1 = this.y.redMul(p.z).redMul(z2z2);
// S2 = Y2 * Z1 * Z1Z1
const s2 = p.y.redMul(this.z).redMul(z1z1);
// H = U2 - U1
const h = u2.redISub(u1);
// r = S2 - S1
const r = s2.redISub(s1);
// H = 0
if (h.isZero()) {
if (!r.isZero())
return this.curve.jpoint();
return this.dbl();
}
// HH = H^2
const hh = h.redSqr();
// HHH = H * HH
const hhh = h.redMul(hh);
// V = U1 * HH
const v = u1.redMul(hh);
// X3 = r^2 - HHH - 2 * V
const nx = r.redSqr().redISub(hhh).redISub(v).redISub(v);
// Y3 = r * (V - X3) - S1 * HHH
const ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(hhh));
// Z3 = Z1 * Z2 * H
const nz = this.z.redMul(p.z).redMul(h);
return this.curve.jpoint(nx, ny, nz);
}
_addJA(p) {
// Assumes Z2 = 1.
// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-madd
// 8M + 3S + 6A + 5*2 (implemented as: 8M + 3S + 7A + 4*2)
// Z1Z1 = Z1^2
const z1z1 = this.z.redSqr();
// U2 = X2 * Z1Z1
const u2 = p.x.redMul(z1z1);
// S2 = Y2 * Z1 * Z1Z1
const s2 = p.y.redMul(this.z).redMul(z1z1);
// H = U2 - X1
const h = u2.redISub(this.x);
// r = 2 * (S2 - Y1)
const r = s2.redISub(this.y).redIMuln(2);
// H = 0
if (h.isZero()) {
if (!r.isZero())
return this.curve.jpoint();
return this.dbl();
}
// I = (2 * H)^2
const i = h.redMuln(2).redSqr();
// J = H * I
const j = h.redMul(i);
// V = X1 * I
const v = this.x.redMul(i);
// X3 = r^2 - J - 2 * V
const nx = r.redSqr().redISub(j).redISub(v).redISub(v);
// Y3 = r * (V - X3) - 2 * Y1 * J
const ny = r.redMul(v.redISub(nx)).redISub(this.y.redMul(j).redIMuln(2));
// Z3 = 2 * Z1 * H
const nz = this.z.redMul(h).redIMuln(2);
return this.curve.jpoint(nx, ny, nz);
}
dbl() {
// P = O
if (this.isInfinity())
return this;
// Y1 = 0
if (this.y.isZero())
return this.curve.jpoint();
// a = 0
if (this.curve.zeroA)
return this._dbl0();
// a = -3
if (this.curve.threeA)
return this._dbl3();
return this._dblJ();
}
_dblJ() {
// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2
// 3M + 6S + 4A + 1*a + 2*2 + 1*3 + 1*4 + 1*8
// (implemented as: 3M + 6S + 5A + 1*a + 1*2 + 1*3 + 1*4 + 1*8)
// XX = X1^2
const xx = this.x.redSqr();
// YY = Y1^2
const yy = this.y.redSqr();
// ZZ = Z1^2
const zz = this.z.redSqr();
// S = 4 * X1 * YY
const s = this.x.redMul(yy).redIMuln(4);
// M = 3 * XX + a * ZZ^2
const m = xx.redIMuln(3).redIAdd(this.curve.a.redMul(zz.redSqr()));
// T = M^2 - 2 * S
const t = m.redSqr().redISub(s).redISub(s);
// X3 = T
const nx = t;
// Y3 = M * (S - T) - 8 * YY^2
const ny = m.redMul(s.redISub(t)).redISub(yy.redSqr().redIMuln(8));
// Z3 = 2 * Y1 * Z1
const nz = this.y.redMul(this.z).redIMuln(2);
return this.curve.jpoint(nx, ny, nz);
}
_dbl0() {
// Assumes a = 0.
// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
// 2M + 5S + 6A + 3*2 + 1*3 + 1*8
// (implemented as: 2M + 5S + 7A + 2*2 + 1*3 + 1*8)
// A = X1^2
const a = this.x.redSqr();
// B = Y1^2
const b = this.y.redSqr();
// C = B^2
const c = b.redSqr();
// + XB2 = (X1 + B)^2
const xb2 = b.redIAdd(this.x).redSqr();
// D = 2 * ((X1 + B)^2 - A - C)
const d = xb2.redISub(a).redISub(c).redIMuln(2);
// E = 3 * A
const e = a.redIMuln(3);
// F = E^2
const f = e.redSqr();
// X3 = F - 2 * D
const nx = f.redISub(d).redISub(d);
// Y3 = E * (D - X3) - 8 * C
const ny = e.redMul(d.redISub(nx)).redISub(c.redIMuln(8));
// Z3 = 2 * Y1 * Z1
const nz = this.y.redMul(this.z).redIMuln(2);
return this.curve.jpoint(nx, ny, nz);
}
_dbl3() {
// Assumes a = -3.
// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
// 3M + 5S + 8A + 1*3 + 1*4 + 2*8
// (implemented as: 3M + 5S + 8A + 1*2 + 1*3 + 1*4 + 1*8)
// delta = Z1^2
const delta = this.z.redSqr();
// gamma = Y1^2
const gamma = this.y.redSqr();
// beta = X1 * gamma
const beta = this.x.redMul(gamma);
// + xmdelta = X1 - delta
const xmdelta = this.x.redSub(delta);
// + xpdelta = X1 + delta
const xpdelta = this.x.redAdd(delta);
// alpha = 3 * (X1 - delta) * (X1 + delta)
const alpha = xmdelta.redMul(xpdelta).redIMuln(3);
// + beta4 = 4 * beta
const beta4 = beta.redIMuln(4);
// + beta8 = 2 * beta4
const beta8 = beta4.redMuln(2);
// + gamma28 = 8 * gamma^2
const gamma28 = gamma.redSqr().redIMuln(8);
// X3 = alpha^2 - 8 * beta
const nx = alpha.redSqr().redISub(beta8);
// Z3 = (Y1 + Z1)^2 - gamma - delta
const nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta);
// Y3 = alpha * (4 * beta - X3) - 8 * gamma^2
const ny = alpha.redMul(beta4.redISub(nx)).redISub(gamma28);
return this.curve.jpoint(nx, ny, nz);
}
getX() {
if (this.isInfinity())
throw new Error('Invalid point.');
this.normalize();
return this.x.fromRed();
}
getY() {
if (this.isInfinity())
throw new Error('Invalid point.');
this.normalize();
return this.y.fromRed();
}
eq(p) {
assert(p instanceof JPoint);
// P = Q
if (this === p)
return true;
// P = O
if (this.isInfinity())
return p.isInfinity();
// Q = O
if (p.isInfinity())
return false;
// Z1 = Z2
if (this.z.eq(p.z)) {
return this.x.eq(p.x)
&& this.y.eq(p.y);
}
// X1 * Z2^2 = X2 * Z1^2
const zz1 = this.z.redSqr();
const zz2 = p.z.redSqr();
const x1 = this.x.redMul(zz2);
const x2 = p.x.redMul(zz1);
if (!x1.eq(x2))
return false;
// Y1 * Z2^3 = Y2 * Z1^3
const zzz1 = zz1.redMul(this.z);
const zzz2 = zz2.redMul(p.z);
const y1 = this.y.redMul(zzz2);
const y2 = p.y.redMul(zzz1);
return y1.eq(y2);
}
cmp(point) {
assert(point instanceof JPoint);
const inf1 = this.isInfinity();
const inf2 = point.isInfinity();
if (inf1 && !inf2)
return -1;
if (!inf1 && inf2)
return 1;
if (inf1 && inf2)
return 0;
return this.order().cmp(point.order())
|| this.getX().cmp(point.getX())
|| this.getY().cmp(point.getY());
}
isInfinity() {
// Z1 = 0
return this.z.isZero();
}
isOrder2() {
if (this.isInfinity())
return false;
return this.y.isZero();
}
isOdd() {
if (this.isInfinity())
return false;
this.normalize();
return this.y.redIsOdd();
}
isEven() {
if (this.isInfinity())
return false;
this.normalize();
return this.y.redIsEven();
}
isSquare() {
if (this.isInfinity())
return false;
return this.y.redMul(this.z).redJacobi() !== -1;
}
eqX(x) {
// Verify that integer `x` is equal to field
// element `x` by scaling it by our z coordinate.
// This optimization is mentioned in and used for
// bip-schnorr[1]. This avoids having to affinize
// the resulting point during verification.
//
// [1] [SCHNORR] "Optimizations".
assert(x instanceof BN);
assert(!x.red);
if (this.isInfinity())
return false;
const zz = this.z.redSqr();
const rx = x.toRed(this.curve.red).redMul(zz);
return this.x.eq(rx);
}
eqR(x) {
// Similar to the optimization above, this
// optimization, suggested by Maxwell[1],
// compares an integer to an X coordinate
// by scaling it.
//
// Since a signature's R value is modulo N
// in ECDSA, we may be dealing with an R
// value greater than N in actuality.
//
// If the equality check fails, we can
// scale N itself by Z and add it to the
// X field element.
//
// [1] https://github.com/bitcoin-core/secp256k1/commit/ce7eb6f
assert(x instanceof BN);
assert(!x.red);
if (!this.curve.smallGap)
return this.toP().eqR(x);
if (this.isInfinity())
return false;
if (x.cmp(this.curve.p) >= 0)
return false;
const zz = this.z.redSqr();
const rx = x.toRed(this.curve.red).redMul(zz);
if (this.x.eq(rx))
return true;
if (this.curve.highOrder)
return false;
if (x.cmp(this.curve.pmodn) >= 0)
return false;
const rn = this.curve.redN.redMul(zz);
rx.redIAdd(rn);
return this.x.eq(rx);
}
toP() {
// P = O
if (this.isInfinity())
return this.curve.point();
this.normalize();
// (X3, Y3) = (X1 / Z1^2, Y1 / Z1^3)
return this.curve.point(this.x, this.y);
}
toJ() {
return this;
}
encode(compact) {
return this.toP().encode(compact);
}
static decode(curve, bytes) {
return ShortPoint.decode(curve, bytes).toJ();
}
encodeX() {
return this.toP().encodeX();
}
static decodeEven(curve, bytes) {
return ShortPoint.decodeEven(curve, bytes).toJ();
}
static decodeSquare(curve, bytes) {
return ShortPoint.decodeSquare(curve, bytes).toJ();
}
toJSON(pre) {
return this.toP().toJSON(pre);
}
toPretty() {
return this.toP().toPretty();
}
static fromJSON(curve, json) {
return ShortPoint.fromJSON(curve, json).toJ();
}
[custom]() {
if (this.isInfinity())
return '<JPoint: Infinity>';
return '<JPoint:'
+ ' x=' + this.x.fromRed().toString(16, 2)
+ ' y=' + this.y.fromRed().toString(16, 2)
+ ' z=' + this.z.fromRed().toString(16, 2)
+ '>';
}
}
/**
* MontCurve
*/
class MontCurve extends Curve {
constructor(conf) {
super(MontPoint, 'mont', conf);
this.a = BN.fromJSON(conf.a).toRed(this.red);
this.b = BN.fromJSON(conf.b).toRed(this.red);
this.bi = this.b.redInvert();
this.a2 = this.a.redAdd(this.two);
this.a24 = this.a2.redMul(this.i4);
this.a3 = this.a.redMul(this.i3);
this.a0 = this.a.redMul(this.bi);
this.b0 = this.bi.redSqr();
this._finalize(conf);
}
static _isomorphism(curveA, curveB, customB) {
// Montgomery Isomorphism.
//
// [MONT3] Page 3, Section 2.1.
//
// Transformation:
//
// A' = A
// B' = B'
//
// Where (B / B') is square.
assert(curveA instanceof BN);
assert(curveB instanceof BN);
assert(customB instanceof BN);
const a = curveA.clone();
const b = customB.clone();
const c = curveB.redDiv(customB);
if (c.redJacobi() !== 1)
throw new Error('Invalid `b` coefficient.');
return [a, b];
}
_short(a0, odd) {
// Montgomery->Short Weierstrass Equivalence.
//
// [MONT2] "Equivalence with Weierstrass curves".
//
// Transformation:
//
// a = (3 - A^2) / (3 * B^2)
// b = (2 * A^3 - 9 * A) / (27 * B^3)
const {a, b, three} = this;
const a2 = a.redSqr();
const a3 = a2.redMul(a);
const b2 = b.redSqr();
const b3 = b2.redMul(b);
const n0 = three.redSub(a2);
const d0 = b2.redMuln(3);
const n1 = a3.redMuln(2).redISub(a.redMuln(9));
const d1 = b3.redMuln(27);
const wa = n0.redDiv(d0);
const wb = n1.redDiv(d1);
if (a0 != null)
return ShortCurve._isomorphism(wa, wb, a0, odd);
return [wa, wb];
}
_mont(b0) {
return MontCurve._isomorphism(this.a, this.b, b0);
}
_edwards(a0, invert = false) {
// Montgomery->Twisted Edwards Transformation.
//
// [MONT1] Page 11, Section 4.3.5.
// [TWISTED] Theorem 3.2, Page 4, Section 3.
//
// Equivalence:
//
// a = (A + 2) / B
// d = (A - 2) / B
//
// Isomorphism:
//
// a = a'
// d = a' * (A - 2) / (A + 2)
//
// Where ((A + 2) / (B * a')) is square.
//
// If `d` is square, we can usually find
// a complete curve by using the `invert`
// option. This will create an isomorphism
// chain of: M(A,B)->E(a,d)->E(d,a).
//
// The equivalence between E(a,d) and
// E(d,a) is:
//
// (x, y) = (x, 1 / y)
//
// Meaning our map to E(d,a) is:
//
// x = u / v
// y = 1 / ((u - 1) / (u + 1))
// = (u + 1) / (u - 1)
assert(typeof invert === 'boolean');
const {two, bi} = this;
const a = this.a.redAdd(two).redMul(bi);
const d = this.a.redSub(two).redMul(bi);
if (invert)
a.swap(d);
if (a0 != null)
return EdwardsCurve._isomorphism(a, d, a0);
return [a, d];
}
_scaleShort(curve) {
assert(curve instanceof ShortCurve);
const [u2, u3] = curve._scale(this);
return [this.field(u2.redInvert()),
this.field(u3.redInvert())];
}
_scaleMont(curve) {
// We can extract the isomorphism factor with:
//
// c = +-sqrt(B / B')
//
// If base points are available, we can do:
//
// c = v' / v
assert(curve instanceof MontCurve);
if (this.g.isInfinity() || curve.g.isInfinity())
return this.field(curve.b).redDivSqrt(this.b);
return this.g.y.redDiv(this.field(curve.g.y));
}
_scaleEdwards(curve, invert) {
// We _could_ do something like:
//
// B = 4 / (a - d)
// c = +-sqrt(B / B')
//
// Which can be reduced to:
//
// c = +-sqrt(4 / ((a - d) * B'))
//
// If base points are available:
//
// v = u' / x
// c = v' / v
//
// Which can be reduced to:
//
// c = v' * x / u'
//
// However, the way our maps are
// written, we can re-use the Edwards
// isomorphism factor when going the
// other direction.
assert(curve instanceof EdwardsCurve);
const c = curve._scale(this, invert);
return this.field(c);
}
_solveY0(x) {
assert(x instanceof BN);
// y^2 = x^3 + A * x^2 + B * x
const a = this.a0;
const b = this.b0;
const x2 = x.redSqr();
const x3 = x2.redMul(x);
const y2 = x3.redIAdd(a.redMul(x2)).redIAdd(b.redMul(x));
return y2;
}
_elligator2(u) {
// Elligator 2.
//
// Distribution: 1/2.
//
// [ELL2] Page 11, Section 5.2.
// [H2EC] "Elligator 2 Method".
// "Mappings for Montgomery curves".
// [SAFE] "Indistinguishability from uniform random strings".
//
// Assumptions:
//
// - y^2 = x^3 + A * x^2 + B * x.
// - A != 0, B != 0.
// - A^2 - 4 * B is non-zero and non-square in F(p).
// - Let z be a non-square in F(p).
// - u != +-sqrt(-1 / z).
//
// Note that Elligator 2 is defined over the form:
//
// y'^2 = x'^3 + A' * x'^2 + B' * x'
//
// Instead of:
//
// B * y^2 = x^3 + A * x^2 + x
//
// Where:
//
// A' = A / B
// B' = 1 / B^2
// x' = x / B
// y' = y / B
//
// And:
//
// x = B * x'
// y = B * y'
//
// This is presumably the result of Elligator 2
// being designed in long Weierstrass form. If
// we want to support B != 1, we need to do the
// conversion.
//
// Map:
//
// g(x) = x^3 + A * x^2 + B * x
// x1 = -A / (1 + z * u^2)
// x1 = -A, if x1 = 0
// x2 = -x1 - A
// x = x1, if g(x1) is square
// = x2, otherwise
// y = sign(u) * abs(sqrt(g(x)))
const lhs = this.a0.redNeg();
const rhs = this.one.redAdd(this.z.redMul(u.redSqr()));
if (rhs.isZero())
rhs.inject(this.one);
const x1 = lhs.redMul(rhs.redInvert());
const x2 = x1.redNeg().redISub(this.a0);
const y1 = this._solveY0(x1);
const y2 = this._solveY0(x2);
const alpha = y1.redIsSquare() | 0;
const x0 = [x1, x2][alpha ^ 1];
const y0 = [y1, y2][alpha ^ 1].redSqrt();
if (y0.redIsOdd() !== u.redIsOdd())
y0.redINeg();
const x = this.b.redMul(x0);
const y = this.b.redMul(y0);
return this.point(x, y);
}
_invert2(p, hint) {
// Inverting the Map (Elligator 2).
//
// [ELL2] Page 12, Section 5.3.
//
// Assumptions:
//
// - -z * x * (x + A) is square in F(p).
// - If r = 1 then x != 0.
// - If r = 2 then x != -A.
//
// Map:
//
// u1 = -(x + A) / (x * z)
// u2 = -x / ((x + A) * z)
// r = random integer in [1,2]
// u = sign(y) * abs(sqrt(ur))
//
// Note that `0 / 0` can only occur if A = 0
// (this violates the assumptions of Elligator 2).
const {x, y} = p;
const r = hint & 1;
const x0 = x.redMul(this.bi);
const y0 = y.redMul(this.bi);
const n = x0.redAdd(this.a0);
const d = x0;
const lhs = [n, d][r].redINeg();
const rhs = [d, n][r].redMul(this.z);
const u = lhs.redDivSqrt(rhs);
if (u.redIsOdd() !== y0.redIsOdd())
u.redINeg();
return u;
}
isElliptic() {
const a2 = this.a.redSqr();
const d = this.b.redMul(a2.redSub(this.four));
// B * (A^2 - 4) != 0
return !d.isZero();
}
jinv() {
// [MONT3] Page 3, Section 2.
const {a, three, four} = this;
const a2 = a.redSqr();
const t0 = a2.redSub(three);
const lhs = t0.redPown(3).redIMuln(256);
const rhs = a2.redSub(four);
if (rhs.isZero())
throw new Error('Curve is not elliptic.');
// (256 * (A^2 - 3)^3) / (A^2 - 4)
return lhs.redDiv(rhs).fromRed();
}
point(x, y) {
return new MontPoint(this, x, y);
}
jpoint(x, y, z) {
assert(x == null && y == null && z == null);
return this.point();
}
xpoint(x, z) {
return new XPoint(this, x, z);
}
solveY2(x) {
// [MONT3] Page 3, Section 2.
// https://hyperelliptic.org/EFD/g1p/auto-montgom.html
assert(x instanceof BN);
// B * y^2 = x^3 + A * x^2 + x
const x2 = x.redSqr();
const x3 = x2.redMul(x);
const by2 = x3.redIAdd(this.a.redMul(x2)).redIAdd(x);
const y2 = by2.redMul(this.bi);
return y2;
}
validate(point) {
assert(point instanceof MontPoint);
if (point.isInfinity())
return true;
const {x, y} = point;
const y2 = this.solveY2(x);
return y.redSqr().eq(y2);
}
pointFromX(x, sign = null) {
assert(x instanceof BN);
assert(sign == null || typeof sign === 'boolean');
if (!x.red)
x = x.toRed(this.red);
const y = this.solveY(x);
if (sign != null) {
if (y.isZero() && sign)
throw new Error('Invalid point.');
if (y.redIsOdd() !== sign)
y.redINeg();
}
return this.point(x, y);
}
isIsomorphic(curve, invert) {
// [MONT3] Page 3, Section 2.1.
assert(curve instanceof Curve);
if (!curve.p.eq(this.p))
return false;
// M(A,B) <-> M(A,B')
if (curve.type === 'mont') {
const a = this.field(curve.a);
const b = this.field(curve.b);
// A' = A
if (!this.a.eq(a))
return false;
// B' != 0
if (this.b.isZero())
return false;
// jacobi(B / B') = 1
const c = b.redDiv(this.b);
return c.redJacobi() === 1;
}
return curve.isIsomorphic(this, invert);
}
isIsogenous(curve) {
assert(curve instanceof Curve);
if (curve.type === 'mont')
return false;
return curve.isIsogenous(this);
}
pointFromShort(point) {
// [ALT] Appendix E.2 (Switching between Alternative Representations).
// [MONT2] "Equivalence with Weierstrass curves"
assert(point instanceof ShortPoint);
if (this.isIsomorphic(point.curve)) {
// Equivalence for E(a,b)->M(A,B):
//
// u = B * x - A / 3
// v = B * y
//
// Undefined if ((u^3 + A * u^2 + u) / B) is not square.
if (point.isInfinity())
return this.point();
const {a3, b} = this;
const [u2, u3] = this._scale(point.curve);
const x = this.field(point.x).redMul(u2);
const y = this.field(point.y).redMul(u3);
const u = b.redMul(x).redISub(a3);
const v = b.redMul(y);
return this.point(u, v);
}
throw new Error('Not implemented.');
}
pointFromMont(point) {
// [MONT3] Page 3, Section 2.1.
assert(point instanceof MontPoint);
if (this.isIsomorphic(point.curve)) {
// Isomorphic maps for M(A,B)<->M(A,B'):
//
// u' = u
// v' = +-sqrt(B / B') * v
//
// Undefined if (B / B') is not square.
if (point.isInfinity())
return this.point();
const c = this._scale(point.curve);
const u = this.field(point.x);
const v = this.field(point.y);
const nu = u;
const nv = c.redMul(v);
return this.point(nu, nv);
}
throw new Error('Not implemented.');
}
pointFromEdwards(point) {
// [RFC7748] Section 4.1 & 4.2.
// [MONT3] Page 6, Section 2.5.
// [TWISTED] Theorem 3.2, Page 4, Section 3.
assert(point instanceof EdwardsPoint);
assert(point.curve.p.eq(this.p));
// Edwards `x`, `y`, `z`.
const x = this.field(point.x);
const y = this.field(point.y);
const z = this.field(point.z);
if (this.isIsogenous(point.curve)) {
// 4-isogeny maps for E(1,d)->M(2-4d,1):
//
// u = y^2 / x^2
// v = (2 - x^2 - y^2) * y / x^3
//
// Undefined for x = 0.
//
// Exceptional Cases:
// - (0, 1) -> O
// - (0, -1) -> (0, 0)
//
// Unexceptional Cases:
// - (+-1, 0) -> (0, 0)
if (point.isInfinity())
return this.point();
if (point.x.isZero())
return this.point(this.zero, this.zero);
const c = z.redSqr().redIMuln(2);
const uu = y.redSqr();
const uz = x.redSqr();
const vv = c.redISub(uz).redISub(uu).redMul(y);
const vz = uz.redMul(x);
return this.cpoint(uu, uz, vv, vz);
}
if (this.isIsomorphic(point.curve, true)) {
// Isomorphic maps for E(d,a)->M(A,B):
//
// u = (y + 1) / (y - 1)
// v = +-sqrt((A - 2) / (B * a)) * u / x
//
// Undefined for x = 0 or y = 1.
//
// Exceptional Cases:
// - (0, 1) -> O
// - (0, -1) -> (0, 0)
//
// Unexceptional Cases:
// - (+-sqrt(1 / a), 0) -> (-1, +-sqrt((A - 2) / B))
if (point.isInfinity())
return this.point();
if (point.x.isZero())
return this.point(this.zero, this.zero);
const c = this._scale(point.curve, true);
const uu = y.redAdd(z);
const uz = y.redSub(z);
const vv = c.redMul(z).redMul(uu);
const vz = x.redMul(uz);
return this.cpoint(uu, uz, vv, vz);
}
if (this.isIsomorphic(point.curve, false)) {
// Isomorphic maps for E(a,d)->M(A,B):
//
// u = (1 + y) / (1 - y)
// v = +-sqrt((A + 2) / (B * a)) * u / x
//
// Undefined for x = 0 or y = 1.
//
// Exceptional Cases:
// - (0, 1) -> O
// - (0, -1) -> (0, 0)
//
// Unexceptional Cases:
// - (+-sqrt(1 / a), 0) -> (1, +-sqrt((A + 2) / B))
if (point.isInfinity())
return this.point();
if (point.x.isZero())
return this.point(this.zero, this.zero);
const c = this._scale(point.curve, false);
const uu = z.redAdd(y);
const uz = z.redSub(y);
const vv = c.redMul(z).redMul(uu);
const vz = x.redMul(uz);
return this.cpoint(uu, uz, vv, vz);
}
throw new Error('Not implemented.');
}
pointFromUniform(u) {
assert(u instanceof BN);
// z = 0 or A = 0
if (this.z.isZero() || this.a.isZero())
throw new Error('Not implemented.');
return this._elligator2(u);
}
pointToUniform(p, hint) {
// Convert a montgomery point to a field
// element by inverting the elligator2 map.
//
// Hint Layout:
//
// [00000000] [0000] [0000]
// | | |
// | | +-- preimage index
// | +--- subgroup
// +-- bits to OR with uniform bytes
assert(p instanceof MontPoint);
assert((hint >>> 0) === hint);
// z = 0 or A = 0
if (this.z.isZero() || this.a.isZero())
throw new Error('Not implemented.');
// P = O
if (p.isInfinity())
throw new Error('Invalid point.');
// Add a random torsion component.
const i = ((hint >>> 4) & 15) % this.torsion.length;
const q = p.add(this.torsion[i]);
return wrapErrors(() => {
return this._invert2(q, hint);
});
}
decodePoint(bytes, sign) {
return MontPoint.decode(this, bytes, sign);
}
encodeX(point) {
assert(point instanceof XPoint);
return point.encode();
}
decodeX(bytes) {
return XPoint.decode(this, bytes);
}
toShort(a0, odd, sign = null) {
const [a, b] = this._short(a0, odd);
const curve = new ShortCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
b: b,
n: this.n,
h: this.h
});
if (sign != null) {
const [, u3] = curve._scale(this);
if (u3.redIsOdd() !== sign)
u3.redINeg();
}
if (!this.g.isInfinity())
curve.g = curve.pointFromMont(this.g);
for (let i = 0; i < this.h.word(0); i++)
curve.torsion[i] = curve.pointFromMont(this.torsion[i]);
return curve;
}
toMont(b0, sign = null) {
const [a, b] = this._mont(b0);
const curve = new MontCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
b: b,
n: this.n,
h: this.h,
z: this.z
});
if (sign != null) {
const c = curve._scale(this);
if (c.redIsOdd() !== sign)
c.redINeg();
}
if (!this.g.isInfinity())
curve.g = curve.pointFromMont(this.g);
for (let i = 0; i < this.h.word(0); i++)
curve.torsion[i] = curve.pointFromMont(this.torsion[i]);
return curve;
}
toEdwards(a0, invert, sign = null) {
const [a, d] = this._edwards(a0, invert);
const curve = new EdwardsCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
d: d,
n: this.n,
h: this.h,
z: this.z
});
if (sign != null) {
const c = curve._scale(this, invert);
if (c.redIsOdd() !== sign)
c.redINeg();
}
if (!this.g.isInfinity()) {
curve.g = curve.pointFromMont(this.g);
curve.g.normalize();
}
if (curve.isComplete()) {
for (let i = 0; i < this.h.word(0); i++) {
curve.torsion[i] = curve.pointFromMont(this.torsion[i]);
curve.torsion[i].normalize();
}
}
return curve;
}
pointFromJSON(json) {
return MontPoint.fromJSON(this, json);
}
toJSON(pre) {
const json = super.toJSON(pre);
json.a = this.a.fromRed().toJSON();
json.b = this.b.fromRed().toJSON();
return json;
}
}
/**
* MontPoint
*/
class MontPoint extends Point {
constructor(curve, x, y) {
assert(curve instanceof MontCurve);
super(curve, types.AFFINE);
this.x = this.curve.zero;
this.y = this.curve.zero;
this.inf = true;
if (x != null)
this._init(x, y);
}
_init(x, y) {
assert(x instanceof BN);
assert(y instanceof BN);
this.x = x;
this.y = y;
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.y.red)
this.y = this.y.toRed(this.curve.red);
this.inf = false;
}
clone() {
if (this.inf)
return this.curve.point();
return this.curve.point(this.x, this.y);
}
scale(a) {
return this.clone();
}
randomize(rng) {
return this.clone();
}
neg() {
// P = O
if (this.inf)
return this;
// -(X1, Y1) = (X1, -Y1)
return this.curve.point(this.x, this.y.redNeg());
}
add(p) {
// [MONT1] Page 8, Section 4.3.2.
//
// Addition Law:
//
// l = (y2 - y1) / (x2 - x1)
// x3 = b * l^2 - a - x1 - x2
// y3 = l * (x1 - x3) - y1
//
// 1I + 2M + 1S + 7A + 1*b
assert(p instanceof MontPoint);
// O + P = P
if (this.inf)
return p;
// P + O = P
if (p.inf)
return this;
// P + P, P + -P
if (this.x.eq(p.x)) {
// P + -P = O
if (!this.y.eq(p.y))
return this.curve.point();
// P + P = 2P
return this.dbl();
}
// H = X2 - X1
const h = p.x.redSub(this.x);
// R = Y2 - Y1
const r = p.y.redSub(this.y);
// L = R / H
const l = r.redDiv(h);
// K = b * L^2
const k = this.curve.b.redMul(l.redSqr());
// X3 = K - a - X1 - X2
const nx = k.redISub(this.curve.a).redISub(this.x).redISub(p.x);
// Y3 = L * (X1 - X3) - Y1
const ny = l.redMul(this.x.redSub(nx)).redISub(this.y);
return this.curve.point(nx, ny);
}
dbl() {
// [MONT1] Page 8, Section 4.3.2.
//
// Addition Law (doubling):
//
// l = (3 * x1^2 + 2 * a * x1 + 1) / (2 * b * y1)
// x3 = b * l^2 - a - 2 * x1
// y3 = l * (x1 - x3) - y1
//
// 1I + 3M + 2S + 7A + 1*a + 1*b + 1*b + 2*2 + 1*3
// P = O
if (this.inf)
return this;
// Y1 = 0
if (this.y.isZero())
return this.curve.point();
// M1 = 3 * X1^2
const m1 = this.x.redSqr().redIMuln(3);
// M2 = 2 * a * X1
const m2 = this.curve.a.redMul(this.x).redIMuln(2);
// M = M1 + M2 + 1
const m = m1.redIAdd(m2).redIAdd(this.curve.one);
// Z = 2 * b * Y1
const z = this.curve.b.redMul(this.y).redIMuln(2);
// L = M / Z
const l = m.redDiv(z);
// K = b * L^2
const k = this.curve.b.redMul(l.redSqr());
// X3 = K - a - 2 * X1
const nx = k.redISub(this.curve.a).redISub(this.x).redISub(this.x);
// Y3 = L * (X1 - X3) - Y1
const ny = l.redMul(this.x.redSub(nx)).redISub(this.y);
return this.curve.point(nx, ny);
}
getX() {
if (this.inf)
throw new Error('Invalid point.');
return this.x.fromRed();
}
getY() {
if (this.inf)
throw new Error('Invalid point.');
return this.y.fromRed();
}
eq(p) {
assert(p instanceof MontPoint);
// P = Q
if (this === p)
return true;
// P = O
if (this.inf)
return p.inf;
// Q = O
if (p.inf)
return false;
// X1 = X2, Y1 = Y2
return this.x.eq(p.x)
&& this.y.eq(p.y);
}
cmp(point) {
assert(point instanceof MontPoint);
if (this.inf && !point.inf)
return -1;
if (!this.inf && point.inf)
return 1;
if (this.inf && point.inf)
return 0;
return this.order().cmp(point.order())
|| this.getX().cmp(point.getX())
|| this.getY().cmp(point.getY());
}
isInfinity() {
// Infinity cannot be represented in
// the affine space, except by a flag.
return this.inf;
}
isOrder2() {
if (this.inf)
return false;
return this.y.isZero();
}
isOdd() {
if (this.inf)
return false;
return this.y.redIsOdd();
}
isEven() {
if (this.inf)
return false;
return this.y.redIsEven();
}
toP() {
return this;
}
toJ() {
return this;
}
toX() {
// (X3, Z3) = (1, 0)
if (this.inf)
return this.curve.xpoint();
// (X3, Z3) = (X1, 1)
return this.curve.xpoint(this.x, this.curve.one);
}
encode() {
return this.toX().encode();
}
static decode(curve, bytes, sign) {
assert(curve instanceof MontCurve);
return curve.decodeX(bytes).toP(sign);
}
toJSON(pre) {
if (this.inf)
return [];
const x = this.getX().toJSON();
const y = this.getY().toJSON();
return [x, y];
}
toPretty() {
if (this.inf)
return [];
const size = this.curve.fieldSize * 2;
const x = toPretty(this.getX(), size);
const y = toPretty(this.getY(), size);
return [x, y];
}
static fromJSON(curve, json) {
assert(curve instanceof MontCurve);
assert(Array.isArray(json));
assert(json.length === 0
|| json.length === 2
|| json.length === 3);
if (json.length === 0)
return curve.point();
const x = BN.fromJSON(json[0]);
const y = BN.fromJSON(json[1]);
return curve.point(x, y);
}
[custom]() {
if (this.inf)
return '<MontPoint: Infinity>';
return '<MontPoint:'
+ ' x=' + this.x.fromRed().toString(16, 2)
+ ' y=' + this.y.fromRed().toString(16, 2)
+ '>';
}
}
/**
* XPoint
*/
class XPoint extends Point {
constructor(curve, x, z) {
assert(curve instanceof MontCurve);
super(curve, types.PROJECTIVE);
this.x = this.curve.one;
this.z = this.curve.zero;
if (x != null)
this._init(x, z);
}
_init(x, z) {
assert(x instanceof BN);
assert(z == null || (z instanceof BN));
this.x = x;
this.z = z || this.curve.one;
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.z.red)
this.z = this.z.toRed(this.curve.red);
}
clone() {
return this.curve.xpoint(this.x, this.z);
}
precompute(power, rng) {
// No-op.
return this;
}
validate() {
if (this.isInfinity())
return true;
// B * y^2 * z = x^3 + A * x^2 * z + x * z^2
const {x, z} = this;
const x2 = x.redSqr();
const x3 = x2.redMul(x);
const z2 = z.redSqr();
const ax2 = this.curve.a.redMul(x2).redMul(z);
const by2 = x3.redIAdd(ax2).redIAdd(x.redMul(z2));
const y2 = by2.redMul(this.curve.bi);
// sqrt(y^2 * z^4) = y * z^2
return y2.redMul(z).redJacobi() !== -1;
}
normalize() {
// https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#scaling-scale
// 1I + 1M
// P = O
if (this.isInfinity())
return this;
// Z1 = 1
if (this.z.eq(this.curve.one))
return this;
// X3 = X1 / Z1
this.x = this.x.redDiv(this.z);
// Z3 = 1
this.z = this.curve.one;
return this;
}
scale(a) {
assert(a instanceof BN);
// P = O
if (this.isInfinity())
return this.curve.xpoint();
// X3 = X1 * A
const nx = this.x.redMul(a);
// Y3 = Y1 * A
const nz = this.z.redMul(a);
return this.curve.xpoint(nx, nz);
}
neg() {
// -(X1, Z1) = (X1, Z1)
return this;
}
dbl() {
// https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3
// 2M + 2S + 4A + 1*a24
// A = X1 + Z1
const a = this.x.redAdd(this.z);
// AA = A^2
const aa = a.redSqr();
// B = X1 - Z1
const b = this.x.redSub(this.z);
// BB = B^2
const bb = b.redSqr();
// C = AA - BB
const c = aa.redSub(bb);
// X3 = AA * BB
const nx = aa.redMul(bb);
// Z3 = C * (BB + a24 * C)
const nz = c.redMul(bb.redIAdd(this.curve.a24.redMul(c)));
return this.curve.xpoint(nx, nz);
}
diffAddDbl(p2, p3) {
// https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#ladder-ladd-1987-m-3
// 6M + 4S + 8A + 1*a24
assert(p2 instanceof XPoint);
assert(p3 instanceof XPoint);
// A = X2 + Z2
const a = p2.x.redAdd(p2.z);
// AA = A^2
const aa = a.redSqr();
// B = X2 - Z2
const b = p2.x.redSub(p2.z);
// BB = B^2
const bb = b.redSqr();
// E = AA - BB
const e = aa.redSub(bb);
// C = X3 + Z3
const c = p3.x.redAdd(p3.z);
// D = X3 - Z3
const d = p3.x.redSub(p3.z);
// DA = D * A
const da = d.redMul(a);
// CB = C * B
const cb = c.redMul(b);
// X5 = Z1 * (DA + CB)^2
const x5 = this.z.redMul(da.redAdd(cb).redSqr());
// Z5 = X1 * (DA - CB)^2
const z5 = this.x.redMul(da.redISub(cb).redSqr());
// X4 = AA * BB
const x4 = aa.redMul(bb);
// Z4 = E * (BB + a24 * E)
const z4 = e.redMul(bb.redIAdd(this.curve.a24.redMul(e)));
return [
this.curve.xpoint(x4, z4),
this.curve.xpoint(x5, z5)
];
}
getX() {
if (this.isInfinity())
throw new Error('Invalid point.');
this.normalize();
return this.x.fromRed();
}
getY(sign) {
return this.toP(sign).getY();
}
eq(p) {
assert(p instanceof XPoint);
// P = Q
if (this === p)
return true;
// P = O
if (this.isInfinity())
return p.isInfinity();
// Q = O
if (p.isInfinity())
return false;
// Z1 = Z2
if (this.z.eq(p.z))
return this.x.eq(p.x);
// X1 * Z2 = X2 * Z1
const x1 = this.x.redMul(p.z);
const x2 = p.x.redMul(this.z);
return x1.eq(x2);
}
cmp(point) {
assert(point instanceof XPoint);
const inf1 = this.isInfinity();
const inf2 = point.isInfinity();
if (inf1 && !inf2)
return -1;
if (!inf1 && inf2)
return 1;
if (inf1 && inf2)
return 0;
return this.order().cmp(point.order())
|| this.getX().cmp(point.getX());
}
isInfinity() {
// Z1 = 0
return this.z.isZero();
}
isOrder2() {
if (this.isInfinity())
return false;
return this.x.isZero();
}
isOdd() {
return false;
}
isEven() {
return false;
}
hasTorsion() {
if (this.isInfinity())
return false;
// X1 = 0, Z1 != 0 (edge case)
if (this.x.isZero())
return true;
return super.hasTorsion();
}
order() {
try {
return this.toP().order();
} catch (e) {
return new BN(1);
}
}
jmul(k) {
// Multiply with the Montgomery Ladder.
//
// [MONT3] Algorithm 4, Page 12, Section 4.2.
//
// Note that any clamping is meant to
// be done _outside_ of this function.
assert(k instanceof BN);
assert(!k.red);
const bits = k.bitLength();
let a = this.curve.xpoint();
let b = this;
for (let i = bits - 1; i >= 0; i--) {
const bit = k.bit(i);
if (bit === 0)
[a, b] = this.diffAddDbl(a, b);
else
[b, a] = this.diffAddDbl(b, a);
}
return a;
}
jmulBlind(k, rng) {
if (!rng)
return this.jmul(k);
// Randomize if available.
return this.randomize(rng).jmul(k);
}
jmulAdd(k1, p2, k2) {
throw new Error('Not implemented.');
}
toP(sign = null) {
assert(sign == null || typeof sign === 'boolean');
if (this.isInfinity())
return this.curve.point();
this.normalize();
return this.curve.pointFromX(this.x, sign);
}
toJ() {
return this;
}
toX() {
return this;
}
key() {
if (this.isInfinity())
return `${this.curve.uid}:oo`;
this.normalize();
const x = this.getX().toString(16);
return `${this.curve.uid}:${x}`;
}
encode() {
// [RFC7748] Section 5.
return this.curve.encodeField(this.getX());
}
static decode(curve, bytes) {
assert(curve instanceof MontCurve);
// [RFC7748] Section 5.
const x = curve.decodeField(bytes);
// We're supposed to ignore the hi bit
// on montgomery points... I think. If
// we don't, the X25519 test vectors
// break, which is pretty convincing
// evidence. This is a no-op for X448.
x.iumaskn(curve.fieldBits);
// Note: montgomery points are meant to be
// reduced by the prime and do not have to
// be explicitly validated in order to do
// the montgomery ladder.
const p = curve.xpoint(x, curve.one);
assert(!p.isInfinity());
return p;
}
toJSON(pre) {
return this.toP().toJSON(pre);
}
toPretty() {
return this.toP().toPretty();
}
static fromJSON(curve, json) {
return MontPoint.fromJSON(curve, json).toX();
}
[custom]() {
if (this.isInfinity())
return '<XPoint: Infinity>';
return '<XPoint:'
+ ' x=' + this.x.fromRed().toString(16, 2)
+ ' z=' + this.z.fromRed().toString(16, 2)
+ '>';
}
}
/**
* EdwardsCurve
*/
class EdwardsCurve extends Curve {
constructor(conf) {
super(EdwardsPoint, 'edwards', conf);
this.a = BN.fromJSON(conf.a).toRed(this.red);
this.d = BN.fromJSON(conf.d).toRed(this.red);
this.s = BN.fromJSON(conf.s || '0').toRed(this.red);
this.si = this.s.isZero() ? this.zero : this.s.redInvert();
this.k = this.d.redMuln(2);
this.smi = -this.d.redNeg().word(0);
this.ad6 = this.a.redAdd(this.d).redMul(this.i6);
this.twisted = !this.a.eq(this.one);
this.oneA = this.a.eq(this.one);
this.mOneA = this.a.eq(this.one.redNeg());
this.smallD = this.prime != null && this.d.redNeg().length === 1;
this.alt = null;
this._finalize(conf);
}
static _isomorphism(curveA, curveD, customA) {
// Twisted Edwards Isomorphism.
//
// [TWISTED] Definition 2.1, Page 3, Section 2.
//
// Transformation:
//
// a' = a'
// d' = a' * d / a
//
// Where (a / a') is square.
assert(curveA instanceof BN);
assert(curveD instanceof BN);
assert(customA instanceof BN);
const a = customA.clone();
const d = customA.redMul(curveD).redDiv(curveA);
const c = curveA.redDiv(customA);
if (c.redJacobi() !== 1)
throw new Error('Invalid `a` coefficient.');
return [a, d];
}
_short(a0, odd) {
// Twisted Edwards->Short Weierstrass Equivalence.
//
// [TWISTEQ] Section 2.
//
// Transformation:
//
// a' = -(a^2 + 14 * a * d + d^2) / 48
// b' = (33 * (a^2 * d + a * d^2) - a^3 - d^3) / 864
const {a, d} = this;
const a2 = a.redSqr();
const a3 = a2.redMul(a);
const d2 = d.redSqr();
const d3 = d2.redMul(d);
const ad14 = a.redMul(d).redIMuln(14);
const a2d = a2.redMul(d);
const ad2 = a.redMul(d2);
const t0 = a2d.redIAdd(ad2).redIMuln(33);
const wa = a2.redAdd(ad14).redIAdd(d2).redDivn(-48);
const wb = t0.redISub(a3).redISub(d3).redDivn(864);
if (a0 != null)
return ShortCurve._isomorphism(wa, wb, a0, odd);
return [wa, wb];
}
_mont(b0, invert = false) {
// Twisted Edwards->Montgomery Transformation.
//
// [TWISTED] Theorem 3.2, Page 4, Section 3.
//
// Equivalence:
//
// A = 2 * (a + d) / (a - d)
// B = 4 / (a - d)
//
// Isomorphism:
//
// A = 2 * (a + d) / (a - d)
// B = B'
//
// Where ((4 / (a - d)) / B') is square.
//
// If `4 / (a - d)` is non-square, we can
// usually force B=1 by using the `invert`
// option. This will create an isomorphism
// chain of: E(a,d)->E(d,a)->M(-A,-B).
//
// The equivalence between E(a,d) and E(d,a)
// is:
//
// (x, y) = (x, 1 / y)
//
// Meaning our map to M(-A,-B) is:
//
// u = (1 + 1 / y) / (1 - 1 / y)
// = (y + 1) / (y - 1)
// v = u / x
assert(typeof invert === 'boolean');
let apd, amd;
if (invert) {
apd = this.d.redAdd(this.a);
amd = this.d.redSub(this.a);
} else {
apd = this.a.redAdd(this.d);
amd = this.a.redSub(this.d);
}
const z = amd.redInvert();
const a = apd.redMuln(2).redMul(z);
const b = z.redMuln(4);
if (b0 != null)
return MontCurve._isomorphism(a, b, b0);
return [a, b];
}
_edwards(a0) {
return EdwardsCurve._isomorphism(this.a, this.d, a0);
}
_scaleShort(curve) {
assert(curve instanceof ShortCurve);
const [u2, u3] = curve._scale(this);
return [this.field(u2.redInvert()),
this.field(u3.redInvert())];
}
_scaleMont(curve, invert = false) {
// Calculate isomorphism factor between
// Twisted Edwards and Montgomery with:
//
// a = (A + 2) / B
// c = +-sqrt(a / a')
//
// Which can be reduced to:
//
// c = +-sqrt((A + 2) / (B * a'))
//
// If base points are available, we can do:
//
// x = u / v
// c = x' / x
//
// Which can be reduced to:
//
// c = v * x' / u
//
// We can now calculate the Edwards `x` with:
//
// x' = c * u / v
//
// And likewise, the Montgomery `v`:
//
// v = c * u / x'
assert(curve instanceof MontCurve);
assert(typeof invert === 'boolean');
if (this.g.isInfinity() || curve.g.isInfinity()) {
const [a] = curve._edwards(null, invert);
return this.field(a).redDivSqrt(this.a);
}
const x = curve.g.x.redDiv(curve.g.y);
return this.g.x.redDiv(this.field(x));
}
_scaleEdwards(curve) {
// We can extract the isomorphism factor with:
//
// c = +-sqrt(a / a')
//
// If base points are available, we can do:
//
// c = x' / x
assert(curve instanceof EdwardsCurve);
if (this.g.isInfinity() || curve.g.isInfinity())
return this.field(curve.a).redDivSqrt(this.a);
return this.g.x.redDiv(this.field(curve.g.x));
}
_mulA(num) {
assert(num instanceof BN);
// n * a = n
if (this.oneA)
return num.clone();
// n * a = -n
if (this.mOneA)
return num.redNeg();
return this.a.redMul(num);
}
_mulD(num) {
assert(num instanceof BN);
// -d < 0x4000000
if (this.smallD)
return num.redMuln(this.smi);
return this.d.redMul(num);
}
_elligator1(t) {
// Elligator 1.
//
// Distribution: 1/2.
//
// [ELL1] Page 6, Section 3.
// Page 15, Appendix A.
// [ELL2] Page 7, Section 3.2.
//
// Assumptions:
//
// - Let p be a prime power congruent to 3 mod 4.
// - Let s be a nonzero element of F(p).
// - Let c = 2 / s^2.
// - Let r = c + 1 / c.
// - Let d = -(c + 1)^2 / (c - 1)^2.
// - (s^2 - 2) * (s^2 + 2) != 0.
// - c * (c - 1) * (c + 1) != 0.
// - r != 0.
// - d is not square.
// - x^2 + y^2 = 1 + d * x^2 * y^2.
// - u * v * X * Y * x * (Y + 1) != 0.
// - Y^2 = X^5 + (r^2 - 2) * X^3 + X.
//
// Elligator 1, as devised by Fouque et al,
// takes place on the hyperelliptic curve of:
//
// y^2 = x^5 + (r^2 - 2) * x^3 + x
//
// Not only must our Edwards curve be complete,
// with a prime congruent to 3 mod 4, and a = 1,
// our curve must be isomorphic to a hyperelliptic
// curve of the above form. Roughly one half of
// all Edwards curves are isomorphic to a curve
// of said form.
//
// We can derive the isomorphism with:
//
// c = (d +- 2 * sqrt(-d) - 1) / (d + 1)
// s = +-sqrt(2 / c)
// r = c + 1 / c
//
// Note that even if your curve is an Elligator 1
// curve, Elligator 2 is probably still preferable,
// as it has nearly the same properties (i.e. the
// same distribution), and is much less complex.
//
// Map:
//
// f(a) = a^((p - 1) / 2)
// u = (1 - t) / (1 + t)
// v = u^5 + (r^2 - 2) * u^3 + u
// X = f(v) * u
// Y = (f(v) * v)^((p + 1) / 4) * f(v) * f(u^2 + 1 / c^2)
// Y = 1, if u = 0
// x = (c - 1) * s * X * (1 + X) / Y
// y = (r * X - (1 + X)^2) / (r * X + (1 + X)^2)
//
// When t = +-1, we create the hyperelliptic
// 2-torsion point of (0, 0). This needs to be
// mapped to (0, -1) in Edwards form, but the x
// denominator becomes zero. As far as I can
// tell, this is the only exceptional case.
//
// The only other exceptional case initially
// appears to be when the y denominator sums to
// zero (when t = sqrt(4 / r + 1)), however, the
// hyperelliptic `X` is negated by the sign of
// `v`, making this impossible.
const {s, si, i2, one, two} = this;
const c = si.redSqr().redIMuln(2);
const ci = s.redSqr().redMul(i2);
const ci2 = ci.redSqr();
const r = c.redAdd(ci);
const r2 = r.redSqr().redISub(two);
const cm1 = c.redSub(one);
const uu = one.redSub(t);
const uz = one.redAdd(t);
const u = uz.isZero() ? uz : uu.redDiv(uz);
const u2 = u.redSqr();
const u3 = u2.redMul(u);
const u5 = u3.redMul(u2);
const v = u5.redAdd(r2.redMul(u3)).redIAdd(u);
const f0 = this.field(v.redJacobi());
const f1 = this.field(u2.redAdd(ci2).redJacobi());
const f2 = f0.redMul(f1);
const X = f0.redMul(u);
const Y = f0.redMul(v).redSqrt().redMul(f2);
const X1 = one.redAdd(X);
const rX = r.redMul(X);
const X12 = X1.redSqr();
const xx = cm1.redMul(s).redMul(X).redMul(X1);
const xz = u.isZero() ? this.one : Y;
const yy = rX.redSub(X12);
const yz = rX.redAdd(X12);
return this.cpoint(xx, xz, yy, yz);
}
_invert1(p, hint) {
// Inverting the Map (Elligator 1).
//
// [ELL1] Page 6, Section 3.
// Page 15, Appendix A.
// [ELL2] Page 7, Section 3.3.
//
// Assumptions:
//
// - y + 1 != 0.
// - (1 + n * r)^2 - 1 is square in F(p).
// - If n * r = -2 then x = 2 * s * (c - 1) * f(c) / r.
// - Y = (c - 1) * s * X * (1 + X) / x.
//
// Map:
//
// f(a) = a^((p - 1) / 2)
// n = (y - 1) / (2 * (y + 1))
// X = -(1 + n * r) + ((1 + n * r)^2 - 1)^((p + 1) / 4)
// z = f((c - 1) * s * X * (1 + X) * x * (X^2 + 1 / c^2))
// u = z * X
// t = (1 - u) / (1 + u)
const {s, si, i2, one} = this;
const {x, y, z} = p;
const sign = hint & 1;
const c = si.redSqr().redIMuln(2);
const ci = s.redSqr().redMul(i2);
const ci2 = ci.redSqr();
const r = c.redAdd(ci);
const cm1 = c.redSub(one);
const nn = y.redSub(z);
const nz = y.redAdd(z).redIMuln(2);
const n = nz.isZero() ? nz : nn.redDiv(nz);
const nr1 = one.redAdd(n.redMul(r));
const w2 = nr1.redSqr().redISub(one);
const w = w2.redSqrt();
const X = w.redSub(nr1);
const X1 = one.redAdd(X);
const YY = cm1.redMul(s).redMul(X).redMul(X1);
const Y = YY.redMul(x.redMul(z));
const X2 = X.redSqr().redIAdd(ci2);
const Z = this.field(Y.redMul(X2).redJacobi());
const u = Z.redMul(X);
const tt = one.redSub(u);
const tz = one.redAdd(u);
const t = tz.isZero() ? tz : tt.redDiv(tz);
if (t.redIsOdd() !== Boolean(sign))
t.redINeg();
return t;
}
_alt() {
if (!this.alt)
this.alt = this.toMont();
return this.alt;
}
isElliptic() {
const ad = this.a.redMul(this.d);
const amd = this.a.redSub(this.d);
// a * d * (a - d) != 0
return !ad.redMul(amd).isZero();
}
jinv() {
// [TWISTED] Definition 2.1, Page 3, Section 2.
const {a, d} = this;
const ad = a.redMul(d);
const amd4 = a.redSub(d).redPown(4);
const a2 = a.redSqr();
const d2 = d.redSqr();
const t0 = a2.redAdd(ad.redMuln(14)).redIAdd(d2);
const lhs = t0.redPown(3).redIMuln(16);
const rhs = ad.redMul(amd4);
if (rhs.isZero())
throw new Error('Curve is not elliptic.');
// 16 * (a^2 + 14 * a * d + d^2)^3 / (a * d * (a - d)^4)
return lhs.redDiv(rhs).fromRed();
}
isComplete() {
return this.a.redJacobi() === 1
&& this.d.redJacobi() === -1;
}
point(x, y, z, t) {
return new EdwardsPoint(this, x, y, z, t);
}
jpoint(x, y, z) {
assert(x == null && y == null && z == null);
return this.point();
}
cpoint(xx, xz, yy, yz) {
assert(xx instanceof BN);
assert(xz instanceof BN);
assert(yy instanceof BN);
assert(yz instanceof BN);
const x = xx.redMul(yz);
const y = yy.redMul(xz);
const z = xz.redMul(yz);
const t = xx.redMul(yy);
return this.point(x, y, z, t);
}
solveX2(y) {
// [RFC8032] Section 5.1.3 & 5.2.3.
assert(y instanceof BN);
// x^2 = (y^2 - 1) / (d * y^2 - a)
const y2 = y.redSqr();
const rhs = this._mulD(y2).redISub(this.a);
const lhs = y2.redISub(this.one);
const x2 = lhs.redDiv(rhs);
return x2;
}
solveX(y) {
// Optimize with inverse square root trick.
//
// Note that `0 / 0` can only occur if
// `a == d` (i.e. the curve is singular).
const y2 = y.redSqr();
const rhs = this._mulD(y2).redISub(this.a);
const lhs = y2.redISub(this.one);
return lhs.redDivSqrt(rhs);
}
solveY2(x) {
assert(x instanceof BN);
// y^2 = (a * x^2 - 1) / (d * x^2 - 1)
const x2 = x.redSqr();
const lhs = this._mulA(x2).redISub(this.one);
const rhs = this._mulD(x2).redISub(this.one);
const y2 = lhs.redDiv(rhs);
return y2;
}
solveY(x) {
// Optimize with inverse square root trick.
//
// Note that `0 / 0` can only occur if
// `a == d` (i.e. the curve is singular).
const x2 = x.redSqr();
const lhs = this._mulA(x2).redISub(this.one);
const rhs = this._mulD(x2).redISub(this.one);
return lhs.redDivSqrt(rhs);
}
validate(point) {
// [TWISTED] Definition 2.1, Page 3, Section 2.
// Page 11, Section 6.
assert(point instanceof EdwardsPoint);
// Z1 = 1
if (point.zOne) {
// a * x^2 + y^2 = 1 + d * x^2 * y^2
const x2 = point.x.redSqr();
const y2 = point.y.redSqr();
const dxy = this._mulD(x2).redMul(y2);
const lhs = this._mulA(x2).redIAdd(y2);
const rhs = this.one.redAdd(dxy);
const tz = point.t;
const xy = point.x.redMul(point.y);
return lhs.eq(rhs) && tz.eq(xy);
}
// (a * x^2 + y^2) * z^2 = z^4 + d * x^2 * y^2
const x2 = point.x.redSqr();
const y2 = point.y.redSqr();
const z2 = point.z.redSqr();
const z4 = z2.redSqr();
const dxy = this._mulD(x2).redMul(y2);
const lhs = this._mulA(x2).redIAdd(y2).redMul(z2);
const rhs = z4.redIAdd(dxy);
const tz = point.t.redMul(point.z);
const xy = point.x.redMul(point.y);
return lhs.eq(rhs) && tz.eq(xy);
}
pointFromX(x, sign = null) {
assert(x instanceof BN);
assert(sign == null || typeof sign === 'boolean');
if (!x.red)
x = x.toRed(this.red);
const y = this.solveY(x);
if (sign != null) {
if (y.isZero() && sign)
throw new Error('Invalid point.');
if (y.redIsOdd() !== sign)
y.redINeg();
}
return this.point(x, y);
}
pointFromY(y, sign = null) {
assert(y instanceof BN);
assert(sign == null || typeof sign === 'boolean');
if (!y.red)
y = y.toRed(this.red);
const x = this.solveX(y);
if (sign != null) {
if (x.isZero() && sign)
throw new Error('Invalid point.');
if (x.redIsOdd() !== sign)
x.redINeg();
}
return this.point(x, y);
}
isIsomorphic(curve, invert = false) {
// [TWISTED] Theorem 3.2, Page 4, Section 3.
// Definition 2.1, Page 3, Section 2.
assert(curve instanceof Curve);
assert(typeof invert === 'boolean');
if (!curve.p.eq(this.p))
return false;
// E(a,d) <-> E(a,b)
if (curve.type === 'short')
return curve.isIsomorphic(this);
// E(a,d) <-> M(A,B)
// E(a,d) <-> M(-A,-B)
if (curve.type === 'mont') {
// A * (a - d) = 2 * (a + d)
const a = this.field(curve.a);
let apd, amd;
if (invert) {
apd = this.d.redAdd(this.a);
amd = this.d.redSub(this.a);
} else {
apd = this.a.redAdd(this.d);
amd = this.a.redSub(this.d);
}
return a.redMul(amd).eq(apd.redIMuln(2));
}
// E(a,d) <-> E(a',a'd/a)
if (curve.type === 'edwards') {
// a' * d = a * d'
const a = this.field(curve.a);
const d = this.field(curve.d);
return this.a.redMul(d).eq(a.redMul(this.d));
}
return false;
}
isIsogenous(curve) {
// Check for the 4-isogenies described by Hamburg:
// https://moderncrypto.org/mail-archive/curves/2016/000806.html
assert(curve instanceof Curve);
if (!curve.p.eq(this.p))
return false;
// E(1,d) <-> M(2-4d,1)
if (curve.type === 'mont') {
if (!this.a.eq(this.one))
return false;
const a = this.field(curve.a);
const b = this.field(curve.b);
const d24 = this.two.redSub(this.d.redMuln(4));
return a.eq(d24) && b.eq(this.one);
}
// E(a,d) <-> E(-a,d-a)
if (curve.type === 'edwards') {
const a = this.field(curve.a);
const d = this.field(curve.d);
return a.eq(this.a.redNeg())
&& d.eq(this.d.redSub(this.a));
}
return false;
}
pointFromShort(point) {
// [TWISTEQ] Section 1.
assert(point instanceof ShortPoint);
if (this.isIsomorphic(point.curve)) {
// Equivalence for E(a,b)->E(a',d'):
//
// x' = (6 * x - a' - d') / (6 * y)
// y' = (12 * x - 5 * a' + d') / (12 * x + a' - 5 * d')
//
// Undefined for x = (5 * d' - a') / 12 or y = 0.
//
// Exceptional Cases:
// - O -> (0, 1)
// - ((a' + d') / 6, 0) -> (0, -1)
// - ((5 * d' - a') / 12, (d' - a') / 4 * sqrt(d')) -> (sqrt(1/d'), oo)
//
// Unexceptional Cases:
// - ((5 * a' - d') / 12, (a' - d') / 4 * sqrt(a')) -> (sqrt(1/a'), 0)
if (point.isInfinity())
return this.point();
if (point.y.isZero())
return this.point(this.zero, this.one.redNeg());
const {a, d} = this;
const [u2, u3] = this._scale(point.curve);
const a5 = a.redMuln(5);
const d5 = d.redMuln(5);
const x = this.field(point.x).redMul(u2);
const y = this.field(point.y).redMul(u3);
const x6 = x.redMuln(6);
const x12 = x.redMuln(12);
const xx = x6.redSub(a).redISub(d);
const xz = y.redMuln(6);
const yy = x12.redSub(a5).redIAdd(d);
const yz = x12.redAdd(a).redISub(d5);
return this.cpoint(xx, xz, yy, yz);
}
throw new Error('Not implemented.');
}
pointFromMont(point) {
// [RFC7748] Section 4.1 & 4.2.
// [MONT3] Page 6, Section 2.5.
// [TWISTED] Theorem 3.2, Page 4, Section 3.
assert(point instanceof MontPoint);
assert(point.curve.p.eq(this.p));
// Montgomery `u`, `v`.
const u = this.field(point.x);
const v = this.field(point.y);
if (this.isIsogenous(point.curve)) {
// 4-isogeny maps for M(2-4d,1)->E(1,d):
//
// x = 4 * v * (u^2 - 1) / (u^4 - 2 * u^2 + 4 * v^2 + 1)
// y = -(u^5 - 2 * u^3 - 4 * u * v^2 + u) /
// (u^5 - 2 * u^2 * v^2 - 2 * u^3 - 2 * v^2 + u)
//
// Undefined for u = 0 and v = 0.
//
// Exceptional Cases:
// - O -> (0, 1)
// - (0, 0) -> (0, 1)
//
// Unexceptional Cases:
// - (-1, +-sqrt(A - 2)) -> (0, 1)
// - (1, +-sqrt(A + 2)) -> (0, -1)
//
// The point (1, v) is invalid on Curve448.
if (point.isInfinity())
return this.point();
if (point.x.isZero())
return this.point();
const u2 = u.redSqr();
const u3 = u2.redMul(u);
const u4 = u3.redMul(u);
const u5 = u4.redMul(u);
const v2 = v.redSqr();
const a = v.redMuln(4);
const b = u2.redSub(this.one);
const c = u2.redMuln(2);
const d = v2.redMuln(4);
const e = u3.redIMuln(2);
const f = u.redMul(v2).redIMuln(4);
const g = u2.redMul(v2).redIMuln(2);
const h = v2.redIMuln(2);
const xx = a.redMul(b);
const xz = u4.redISub(c).redIAdd(d).redIAdd(this.one);
const yy = u5.redSub(e).redISub(f).redIAdd(u).redINeg();
const yz = u5.redISub(g).redISub(e).redISub(h).redIAdd(u);
return this.cpoint(xx, xz, yy, yz).divn(4);
}
if (this.isIsomorphic(point.curve, true)) {
// Isomorphic maps for M(-A,-B)->E(a,d):
//
// x = +-sqrt((A - 2) / (B * a)) * u / v
// y = (u + 1) / (u - 1)
//
// Undefined for u = 1 or v = 0.
//
// Exceptional Cases:
// - O -> (0, 1)
// - (0, 0) -> (0, -1)
// - (1, +-sqrt((A + 2) / B)) -> (+-sqrt(1 / d), oo)
//
// Unexceptional Cases:
// - (-1, +-sqrt((A - 2) / B)) -> (+-sqrt(1 / a), 0)
//
// The point (1, v) is invalid on Curve448.
if (point.isInfinity())
return this.point();
if (point.x.isZero())
return this.point(this.zero, this.one.redNeg());
const c = this._scale(point.curve, true);
const xx = c.redMul(u);
const xz = v;
const yy = u.redAdd(this.one);
const yz = u.redSub(this.one);
return this.cpoint(xx, xz, yy, yz);
}
if (this.isIsomorphic(point.curve, false)) {
// Isomorphic maps for M(A,B)->E(a,d):
//
// x = +-sqrt((A + 2) / (B * a)) * u / v
// y = (u - 1) / (u + 1)
//
// Undefined for u = -1 or v = 0.
//
// Exceptional Cases:
// - O -> (0, 1)
// - (0, 0) -> (0, -1)
// - (-1, +-sqrt((A - 2) / B)) -> (+-sqrt(1 / d), oo)
//
// Unexceptional Cases:
// - (1, +-sqrt((A + 2) / B)) -> (+-sqrt(1 / a), 0)
//
// The point (-1, v) is invalid on Curve25519.
if (point.isInfinity())
return this.point();
if (point.x.isZero())
return this.point(this.zero, this.one.redNeg());
const c = this._scale(point.curve, false);
const xx = c.redMul(u);
const xz = v;
const yy = u.redSub(this.one);
const yz = u.redAdd(this.one);
return this.cpoint(xx, xz, yy, yz);
}
throw new Error('Not implemented.');
}
pointFromEdwards(point) {
// [TWISTED] Definition 2.1, Page 3, Section 2.
// [ISOGENY] Page 2, Section 2.
assert(point instanceof EdwardsPoint);
assert(point.curve.p.eq(this.p));
// Edwards `x`, `y`, `z`, `t`.
const a = this.field(point.curve.a);
const x = this.field(point.x);
const y = this.field(point.y);
const z = this.field(point.z);
const t = this.field(point.t);
if (this.isIsogenous(point.curve)) {
// 4-isogeny maps for E(a,d)<->E(-a,d-a):
//
// x' = (2 * x * y) / (y^2 - a * x^2)
// y' = (y^2 + a * x^2) / (2 - y^2 - a * x^2)
//
// Undefined for y^2 - a * x^2 = 0
// or y^2 + a * x^2 = 2.
const xy = x.redMul(y);
const x2 = x.redSqr();
const y2 = y.redSqr();
const z2 = z.redSqr();
const ax2 = a.redMul(x2);
const xx = xy.redIMuln(2);
const xz = y2.redSub(ax2);
const yy = y2.redAdd(ax2);
const yz = z2.redIMuln(2).redISub(yy);
const p = this.cpoint(xx, xz, yy, yz);
return !this.twisted ? p.divn(4) : p;
}
if (this.isIsomorphic(point.curve)) {
// Isomorphic maps for E(a,d)<->E(a',a'd/a):
//
// x' = +-sqrt(a / a') * x
// y' = y
//
// Undefined when (a / a') is not square.
const c = this._scale(point.curve);
const nx = c.redMul(x);
const ny = y;
const nz = z;
const nt = c.redMul(t);
return this.point(nx, ny, nz, nt);
}
throw new Error('Not implemented.');
}
pointFromUniform(u, curve = null) {
assert(u instanceof BN);
assert(u.red === this.red);
assert(curve == null || (curve instanceof MontCurve));
if (!curve)
curve = this._alt();
const u0 = curve.field(u);
const p0 = curve.pointFromUniform(u0);
return this.pointFromMont(p0);
}
pointToUniform(p, hint, curve = null) {
// Convert an edwards point to a field
// element by inverting the elligator2 map.
//
// Hint Layout:
//
// [00000000] [0000] [0000]
// | | |
// | | +-- preimage index
// | +--- subgroup
// +-- bits to OR with uniform bytes
assert(p instanceof EdwardsPoint);
assert((hint >>> 0) === hint);
assert(curve == null || (curve instanceof MontCurve));
if (!curve)
curve = this._alt();
// Add a random torsion component.
const i = ((hint >> 4) & 15) % this.torsion.length;
const q = p.add(this.torsion[i]);
// Convert and invert.
const p0 = curve.pointFromEdwards(q);
const u0 = curve.pointToUniform(p0, hint & 15);
return this.field(u0);
}
pointFromHash(bytes, pake, curve = null) {
assert(curve == null || (curve instanceof MontCurve));
if (!curve)
curve = this._alt();
const p0 = curve.pointFromHash(bytes, pake);
return this.pointFromMont(p0);
}
pointToHash(p, subgroup, rng, curve = null) {
assert(p instanceof EdwardsPoint);
assert((subgroup >>> 0) === subgroup);
assert(curve == null || (curve instanceof MontCurve));
if (!curve)
curve = this._alt();
// Add a random torsion component.
const i = subgroup % this.torsion.length;
const q = p.add(this.torsion[i]);
// Convert and invert.
const p0 = curve.pointFromEdwards(q);
return curve.pointToHash(p0, 0, rng);
}
decodePoint(bytes) {
return EdwardsPoint.decode(this, bytes);
}
toShort(a0, odd, sign = null) {
const [a, b] = this._short(a0, odd);
const curve = new ShortCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
b: b,
n: this.n,
h: this.h
});
if (sign != null) {
const [, u3] = curve._scale(this);
if (u3.redIsOdd() !== sign)
u3.redINeg();
}
if (!this.g.isInfinity())
curve.g = curve.pointFromEdwards(this.g);
for (let i = 0; i < this.h.word(0); i++)
curve.torsion[i] = curve.pointFromEdwards(this.torsion[i]);
return curve;
}
toMont(b0, invert, sign = null) {
const [a, b] = this._mont(b0, invert);
const curve = new MontCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
b: b,
n: this.n,
h: this.h,
z: this.z
});
if (sign != null) {
const c = this._scale(curve, invert);
if (c.redIsOdd() !== sign)
c.redINeg();
}
if (!this.g.isInfinity())
curve.g = curve.pointFromEdwards(this.g);
for (let i = 0; i < this.h.word(0); i++)
curve.torsion[i] = curve.pointFromEdwards(this.torsion[i]);
return curve;
}
toEdwards(a0, sign = null) {
const [a, d] = this._edwards(a0);
const curve = new EdwardsCurve({
red: this.red,
prime: this.prime,
p: this.p,
a: a,
d: d,
n: this.n,
h: this.h,
z: this.z
});
if (sign != null) {
const c = curve._scale(this);
if (c.redIsOdd() !== sign)
c.redINeg();
}
if (!this.g.isInfinity()) {
curve.g = curve.pointFromEdwards(this.g);
curve.g.normalize();
}
if (curve.isComplete()) {
for (let i = 0; i < this.h.word(0); i++) {
curve.torsion[i] = curve.pointFromEdwards(this.torsion[i]);
curve.torsion[i].normalize();
}
}
return curve;
}
pointFromJSON(json) {
return EdwardsPoint.fromJSON(this, json);
}
toJSON(pre) {
const json = super.toJSON(pre);
json.a = this.a.fromRed().toJSON();
json.d = this.d.fromRed().toJSON();
if (!this.s.isZero())
json.s = this.s.fromRed().toJSON();
return json;
}
}
/**
* EdwardsPoint
*/
class EdwardsPoint extends Point {
constructor(curve, x, y, z, t) {
assert(curve instanceof EdwardsCurve);
super(curve, types.EXTENDED);
this.x = this.curve.zero;
this.y = this.curve.one;
this.z = this.curve.one;
this.t = this.curve.zero;
this.zOne = true;
if (x != null)
this._init(x, y, z, t);
}
_init(x, y, z, t) {
assert(x instanceof BN);
assert(y instanceof BN);
assert(z == null || (z instanceof BN));
assert(t == null || (t instanceof BN));
this.x = x;
this.y = y;
this.z = z || this.curve.one;
this.t = t || null;
if (!this.x.red)
this.x = this.x.toRed(this.curve.red);
if (!this.y.red)
this.y = this.y.toRed(this.curve.red);
if (!this.z.red)
this.z = this.z.toRed(this.curve.red);
if (this.t && !this.t.red)
this.t = this.t.toRed(this.curve.red);
this.zOne = this.z.eq(this.curve.one);
this._check();
if (!this.t) {
this.t = this.x.redMul(this.y);
if (!this.zOne)
this.t = this.t.redDiv(this.z);
}
}
_check() {
// In order to achieve complete
// addition formulas, `a` must
// be a square (always the case
// for a=1), and `d` must be a
// non-square.
//
// If this is not the case, the
// addition formulas may have
// exceptional cases where Z3=0.
//
// In particular, this can occur
// when: Q*h = -P*h and Q != -P.
//
// This is assuming 4-torsion is
// involved (the 4-torsion point
// is _not_ representable when
// `d` is square).
if (this.z.isZero())
throw new Error('Invalid point.');
}
clone() {
return this.curve.point(this.x, this.y, this.z, this.t);
}
normalize() {
// https://hyperelliptic.org/EFD/g1p/auto-edwards-projective.html#scaling-z
// 1I + 2M (+ 1M if extended)
// Z1 = 1
if (this.zOne)
return this;
// A = 1 / Z1
const a = this.z.redInvert();
// X3 = X1 * A
this.x = this.x.redMul(a);
// Y3 = Y1 * A
this.y = this.y.redMul(a);
// T3 = T1 * A
this.t = this.t.redMul(a);
// Z3 = 1
this.z = this.curve.one;
this.zOne = true;
return this;
}
scale(a) {
assert(a instanceof BN);
// X3 = X1 * A
const nx = this.x.redMul(a);
// Y3 = Y1 * A
const ny = this.y.redMul(a);
// Z3 = Z1 * A
const nz = this.z.redMul(a);
// T3 = T1 * A
const nt = this.t.redMul(a);
return this.curve.point(nx, ny, nz, nt);
}
neg() {
// -(X1, Y1, Z1, T1) = (-X1, Y1, Z1, -T1)
const nx = this.x.redNeg();
const ny = this.y;
const nz = this.z;
const nt = this.t.redNeg();
return this.curve.point(nx, ny, nz, nt);
}
add(p) {
assert(p instanceof EdwardsPoint);
// P = O
if (this.isInfinity())
return p;
// Q = O
if (p.isInfinity())
return this;
// Z1 = 1
if (this.zOne)
return p._add(this);
return this._add(p);
}
_add(p) {
// a = -1
if (this.curve.mOneA)
return this._addM1(p);
return this._addA(p);
}
_addM1(p) {
// Assumes a = -1.
//
// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3
// 8M + 8A + 1*k + 1*2
//
// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-madd-2008-hwcd-3
// 7M + 8A + 1*k + 1*2
// A = (Y1 - X1) * (Y2 - X2)
const a = this.y.redSub(this.x).redMul(p.y.redSub(p.x));
// B = (Y1 + X1) * (Y2 + X2)
const b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x));
// C = T1 * k * T2
const c = this.t.redMul(this.curve.k).redMul(p.t);
// D = Z1 * 2 * Z2
const d = p.zOne ? this.z.redAdd(this.z) : this.z.redMul(p.z).redIMuln(2);
// E = B - A
const e = b.redSub(a);
// F = D - C
const f = d.redSub(c);
// G = D + C
const g = d.redIAdd(c);
// H = B + A
const h = b.redIAdd(a);
// X3 = E * F
const nx = e.redMul(f);
// Y3 = G * H
const ny = g.redMul(h);
// T3 = E * H
const nt = e.redMul(h);
// Z3 = F * G
const nz = f.redMul(g);
return this.curve.point(nx, ny, nz, nt);
}
_addA(p) {
// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
// 9M + 7A + 1*a + 1*d
//
// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd
// 8M + 7A + 1*a + 1*d
// A = X1 * X2
const a = this.x.redMul(p.x);
// B = Y1 * Y2
const b = this.y.redMul(p.y);
// C = T1 * d * T2
const c = this.curve._mulD(this.t).redMul(p.t);
// D = Z1 * Z2
const d = p.zOne ? this.z.clone() : this.z.redMul(p.z);
// + XYXY = (X1 + Y1) * (X2 + Y2)
const xyxy = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y));
// E = (X1 + Y1) * (X2 + Y2) - A - B
const e = xyxy.redISub(a).redISub(b);
// F = D - C
const f = d.redSub(c);
// G = D + C
const g = d.redIAdd(c);
// H = B - a * A
const h = b.redISub(this.curve._mulA(a));
// X3 = E * F
const nx = e.redMul(f);
// Y3 = G * H
const ny = g.redMul(h);
// T3 = E * H
const nt = e.redMul(h);
// Z3 = F * G
const nz = f.redMul(g);
return this.curve.point(nx, ny, nz, nt);
}
dbl() {
// P = O
if (this.isInfinity())
return this;
return this._dbl();
}
_dbl() {
// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
// 4M + 4S + 6A + 1*a + 1*2
//
// https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-mdbl-2008-hwcd
// 3M + 4S + 7A + 1*a + 1*2
// A = X1^2
const a = this.x.redSqr();
// B = Y1^2
const b = this.y.redSqr();
// C = 2 * Z1^2
const c = this.zOne ? this.curve.two : this.z.redSqr().redIMuln(2);
// D = a * A
const d = this.curve._mulA(a);
// E = (X1 + Y1)^2 - A - B
const e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b);
// G = D + B
const g = d.redAdd(b);
// F = G - C
const f = g.redSub(c);
// H = D - B
const h = d.redISub(b);
// X3 = E * F
const nx = e.redMul(f);
// Y3 = G * H
const ny = g.redMul(h);
// T3 = E * H
const nt = e.redMul(h);
// Z3 = F * G
const nz = f.redMul(g);
return this.curve.point(nx, ny, nz, nt);
}
getX() {
this.normalize();
return this.x.fromRed();
}
getY() {
this.normalize();
return this.y.fromRed();
}
eq(p) {
assert(p instanceof EdwardsPoint);
assert(!this.z.isZero());
assert(!p.z.isZero());
// P = Q
if (this === p)
return true;
// Z1 = Z2
if (this.z.eq(p.z)) {
return this.x.eq(p.x)
&& this.y.eq(p.y);
}
// X1 * Z2 = X2 * Z1
const x1 = this.x.redMul(p.z);
const x2 = p.x.redMul(this.z);
if (!x1.eq(x2))
return false;
const y1 = this.y.redMul(p.z);
const y2 = p.y.redMul(this.z);
return y1.eq(y2);
}
cmp(point) {
assert(point instanceof EdwardsPoint);
return this.order().cmp(point.order())
|| this.getY().cmp(point.getY())
|| this.getX().cmp(point.getX());
}
isInfinity() {
assert(!this.z.isZero());
// X1 = 0
if (!this.x.isZero())
return false;
// Y1 = Z1
return this.y.eq(this.z);
}
isOrder2() {
if (this.isInfinity())
return false;
return this.x.isZero();
}
isOdd() {
this.normalize();
return this.x.redIsOdd();
}
isEven() {
this.normalize();
return this.x.redIsEven();
}
toP() {
return this.normalize();
}
toJ() {
return this;
}
encode() {
// [RFC8032] Section 5.1.2.
const y = this.getY();
// Note: `x` normalized from `getY()` call.
y.setn(this.curve.signBit, this.x.redIsOdd());
return this.curve.encodeAdjusted(y);
}
static decode(curve, bytes) {
// [RFC8032] Section 5.1.3.
assert(curve instanceof EdwardsCurve);
const y = curve.decodeAdjusted(bytes);
const sign = y.testn(curve.signBit) !== 0;
y.setn(curve.signBit, 0);
if (y.cmp(curve.p) >= 0)
throw new Error('Invalid point.');
return curve.pointFromY(y, sign);
}
toJSON(pre) {
if (this.isInfinity())
return [];
const x = this.getX().toJSON();
const y = this.getY().toJSON();
if (pre === true && this.pre)
return [x, y, this.pre.toJSON()];
return [x, y];
}
toPretty() {
const size = this.curve.fieldSize * 2;
const x = toPretty(this.getX(), size);
const y = toPretty(this.getY(), size);
return [x, y];
}
static fromJSON(curve, json) {
assert(curve instanceof EdwardsCurve);
assert(Array.isArray(json));
assert(json.length === 0
|| json.length === 2
|| json.length === 3);
if (json.length === 0)
return curve.point();
const x = BN.fromJSON(json[0]);
const y = BN.fromJSON(json[1]);
const point = curve.point(x, y);
if (json.length > 2 && json[2] != null)
point.pre = Precomp.fromJSON(point, json[2]);
return point;
}
[custom]() {
if (this.isInfinity())
return '<EdwardsPoint: Infinity>';
return '<EdwardsPoint:'
+ ' x=' + this.x.fromRed().toString(16, 2)
+ ' y=' + this.y.fromRed().toString(16, 2)
+ ' z=' + this.z.fromRed().toString(16, 2)
+ '>';
}
}
/**
* Precomp
*/
class Precomp {
constructor() {
this.naf = null;
this.windows = null;
this.doubles = null;
this.blinding = null;
this.beta = null;
}
map(func) {
assert(typeof func === 'function');
const out = new this.constructor();
if (this.naf)
out.naf = this.naf.map(func);
if (this.doubles)
out.doubles = this.doubles.map(func);
return out;
}
toJSON() {
return {
naf: this.naf ? this.naf.toJSON() : null,
windows: this.windows ? this.windows.toJSON() : null,
doubles: this.doubles ? this.doubles.toJSON() : null,
blinding: this.blinding ? this.blinding.toJSON() : undefined
};
}
fromJSON(point, json) {
assert(point instanceof Point);
assert(json && typeof json === 'object');
if (json.naf != null)
this.naf = NAF.fromJSON(point, json.naf);
if (json.windows != null)
this.windows = Windows.fromJSON(point, json.windows);
if (json.doubles != null)
this.doubles = Doubles.fromJSON(point, json.doubles);
if (json.blinding != null)
this.blinding = Blinding.fromJSON(point, json.blinding);
return this;
}
static fromJSON(point, json) {
return new this().fromJSON(point, json);
}
}
/**
* NAF
*/
class NAF {
constructor(width, points) {
this.width = width;
this.points = points;
}
map(func) {
assert(typeof func === 'function');
const {width} = this;
const points = [];
for (const point of this.points)
points.push(func(point));
return new this.constructor(width, points);
}
toJSON() {
return {
width: this.width,
points: this.points.slice(1).map((point) => {
return point.toJSON();
})
};
}
static fromJSON(point, json) {
assert(point instanceof Point);
assert(json && typeof json === 'object');
assert((json.width >>> 0) === json.width);
assert(Array.isArray(json.points));
const {curve} = point;
const {width} = json;
const points = [point];
for (const item of json.points)
points.push(curve.pointFromJSON(item));
return new this(width, points);
}
}
/**
* Windows
*/
class Windows {
constructor(width, bits, points) {
this.width = width;
this.bits = bits;
this.points = points;
}
toJSON() {
return {
width: this.width,
bits: this.bits,
points: this.points.slice(1).map((point) => {
return point.toJSON();
})
};
}
static fromJSON(point, json) {
assert(point instanceof Point);
assert(json && typeof json === 'object');
assert((json.width >>> 0) === json.width);
assert((json.bits >>> 0) === json.bits);
assert(Array.isArray(json.points));
const {curve} = point;
const {width, bits} = json;
const points = [point];
for (const item of json.points)
points.push(curve.pointFromJSON(item));
return new this(width, bits, points);
}
}
/**
* Doubles
*/
class Doubles {
constructor(step, points) {
this.step = step;
this.points = points;
}
map(func) {
assert(typeof func === 'function');
const {step} = this;
const points = [];
for (const point of this.points)
points.push(func(point));
return new this.constructor(step, points);
}
toJSON() {
return {
step: this.step,
points: this.points.slice(1).map((point) => {
return point.toJSON();
})
};
}
static fromJSON(point, json) {
assert(point instanceof Point);
assert(json && typeof json === 'object');
assert((json.step >>> 0) === json.step);
assert(Array.isArray(json.points));
const {curve} = point;
const {step} = json;
const points = [point];
for (const item of json.points)
points.push(curve.pointFromJSON(item));
return new this(step, points);
}
}
/**
* Blinding
*/
class Blinding {
constructor(blind, unblind) {
this.blind = blind;
this.unblind = unblind;
}
toJSON() {
return {
blind: this.blind.toJSON(),
unblind: this.unblind.toJSON()
};
}
static fromJSON(point, json) {
assert(point instanceof Point);
assert(json && typeof json === 'object');
const {curve} = point;
const blind = BN.fromJSON(json.blind);
const unblind = curve.pointFromJSON(json.unblind);
return new this(blind, unblind);
}
}
/**
* Endo
*/
class Endo {
constructor(beta, lambda, basis, pre) {
this.beta = beta;
this.lambda = lambda;
this.basis = basis;
this.pre = pre;
}
toJSON() {
return {
beta: this.beta.fromRed().toJSON(),
lambda: this.lambda.toJSON(),
basis: [
this.basis[0].toJSON(),
this.basis[1].toJSON()
],
pre: [
this.pre[0],
this.pre[1].toJSON(),
this.pre[2].toJSON()
]
};
}
static fromJSON(curve, json) {
assert(curve instanceof Curve);
assert(json && typeof json === 'object');
assert(Array.isArray(json.basis));
assert(Array.isArray(json.pre));
assert(json.basis.length === 2);
assert(json.pre.length === 3);
assert((json.pre[0] >>> 0) === json.pre[0]);
const beta = BN.fromJSON(json.beta).toRed(curve.red);
const lambda = BN.fromJSON(json.lambda);
const basis = [
Vector.fromJSON(json.basis[0]),
Vector.fromJSON(json.basis[1])
];
const pre = [
json.pre[0],
BN.fromJSON(json.pre[1]),
BN.fromJSON(json.pre[2])
];
return new this(beta, lambda, basis, pre);
}
}
/**
* Vector
*/
class Vector {
constructor(a, b) {
this.a = a;
this.b = b;
}
toJSON() {
return {
a: this.a.toJSON(),
b: this.b.toJSON()
};
}
static fromJSON(json) {
assert(json && typeof json === 'object');
const a = BN.fromJSON(json.a);
const b = BN.fromJSON(json.b);
return new this(a, b);
}
}
/**
* P192
* https://tinyurl.com/fips-186-2 (page 29)
* https://tinyurl.com/fips-186-3 (page 88)
*/
class P192 extends ShortCurve {
constructor(pre) {
super({
id: 'P192',
ossl: 'prime192v1',
type: 'short',
endian: 'be',
hash: 'SHA256',
prime: 'p192',
// 2^192 - 2^64 - 1 (= 3 mod 4)
p: ['ffffffff ffffffff ffffffff fffffffe',
'ffffffff ffffffff'],
// -3 mod p
a: ['ffffffff ffffffff ffffffff fffffffe',
'ffffffff fffffffc'],
b: ['64210519 e59c80e7 0fa7e9ab 72243049',
'feb8deec c146b9b1'],
n: ['ffffffff ffffffff ffffffff 99def836',
'146bc9b1 b4d22831'],
h: '1',
// Icart
z: '-5',
g: [
['188da80e b03090f6 7cbf20eb 43a18800',
'f4ff0afd 82ff1012'],
['07192b95 ffc8da78 631011ed 6b24cdd5',
'73f977a1 1e794811'],
pre
]
});
}
}
/**
* P224
* https://tinyurl.com/fips-186-2 (page 30)
* https://tinyurl.com/fips-186-3 (page 88)
*/
class P224 extends ShortCurve {
constructor(pre) {
super({
id: 'P224',
ossl: 'secp224r1',
type: 'short',
endian: 'be',
hash: 'SHA256',
prime: 'p224',
// 2^224 - 2^96 + 1 (1 mod 16)
p: ['ffffffff ffffffff ffffffff ffffffff',
'00000000 00000000 00000001'],
// -3 mod p
a: ['ffffffff ffffffff ffffffff fffffffe',
'ffffffff ffffffff fffffffe'],
b: ['b4050a85 0c04b3ab f5413256 5044b0b7',
'd7bfd8ba 270b3943 2355ffb4'],
n: ['ffffffff ffffffff ffffffff ffff16a2',
'e0b8f03e 13dd2945 5c5c2a3d'],
h: '1',
// SSWU
z: '1f',
g: [
['b70e0cbd 6bb4bf7f 321390b9 4a03c1d3',
'56c21122 343280d6 115c1d21'],
['bd376388 b5f723fb 4c22dfe6 cd4375a0',
'5a074764 44d58199 85007e34'],
pre
]
});
}
}
/**
* P256
* https://tinyurl.com/fips-186-2 (page 31)
* https://tinyurl.com/fips-186-3 (page 89)
*/
class P256 extends ShortCurve {
constructor(pre) {
super({
id: 'P256',
ossl: 'prime256v1',
type: 'short',
endian: 'be',
hash: 'SHA256',
prime: null,
// 2^256 - 2^224 + 2^192 + 2^96 - 1 (= 3 mod 4)
p: ['ffffffff 00000001 00000000 00000000',
'00000000 ffffffff ffffffff ffffffff'],
// -3 mod p
a: ['ffffffff 00000001 00000000 00000000',
'00000000 ffffffff ffffffff fffffffc'],
b: ['5ac635d8 aa3a93e7 b3ebbd55 769886bc',
'651d06b0 cc53b0f6 3bce3c3e 27d2604b'],
n: ['ffffffff 00000000 ffffffff ffffffff',
'bce6faad a7179e84 f3b9cac2 fc632551'],
h: '1',
// SSWU
z: '-a',
g: [
['6b17d1f2 e12c4247 f8bce6e5 63a440f2',
'77037d81 2deb33a0 f4a13945 d898c296'],
['4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16',
'2bce3357 6b315ece cbb64068 37bf51f5'],
pre
]
});
}
}
/**
* P384
* https://tinyurl.com/fips-186-2 (page 32)
* https://tinyurl.com/fips-186-3 (page 89)
*/
class P384 extends ShortCurve {
constructor(pre) {
super({
id: 'P384',
ossl: 'secp384r1',
type: 'short',
endian: 'be',
hash: 'SHA384',
prime: null,
// 2^384 - 2^128 - 2^96 + 2^32 - 1 (= 3 mod 4)
p: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff fffffffe',
'ffffffff 00000000 00000000 ffffffff'],
// -3 mod p
a: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff fffffffe',
'ffffffff 00000000 00000000 fffffffc'],
b: ['b3312fa7 e23ee7e4 988e056b e3f82d19',
'181d9c6e fe814112 0314088f 5013875a',
'c656398d 8a2ed19d 2a85c8ed d3ec2aef'],
n: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff c7634d81 f4372ddf',
'581a0db2 48b0a77a ecec196a ccc52973'],
h: '1',
// Icart
z: '-c',
g: [
['aa87ca22 be8b0537 8eb1c71e f320ad74',
'6e1d3b62 8ba79b98 59f741e0 82542a38',
'5502f25d bf55296c 3a545e38 72760ab7'],
['3617de4a 96262c6f 5d9e98bf 9292dc29',
'f8f41dbd 289a147c e9da3113 b5f0b8c0',
'0a60b1ce 1d7e819d 7a431d7c 90ea0e5f'],
pre
]
});
}
}
/**
* P521
* https://tinyurl.com/fips-186-2 (page 33)
* https://tinyurl.com/fips-186-3 (page 90)
*/
class P521 extends ShortCurve {
constructor(pre) {
super({
id: 'P521',
ossl: 'secp521r1',
type: 'short',
endian: 'be',
hash: 'SHA512',
prime: 'p521',
// 2^521 - 1 (= 3 mod 4)
p: ['000001ff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff'],
// -3 mod p
a: ['000001ff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'fffffffc'],
b: ['00000051 953eb961 8e1c9a1f 929a21a0',
'b68540ee a2da725b 99b315f3 b8b48991',
'8ef109e1 56193951 ec7e937b 1652c0bd',
'3bb1bf07 3573df88 3d2c34f1 ef451fd4',
'6b503f00'],
n: ['000001ff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'fffffffa 51868783 bf2f966b 7fcc0148',
'f709a5d0 3bb5c9b8 899c47ae bb6fb71e',
'91386409'],
h: '1',
// SSWU
z: '-4',
g: [
['000000c6 858e06b7 0404e9cd 9e3ecb66',
'2395b442 9c648139 053fb521 f828af60',
'6b4d3dba a14b5e77 efe75928 fe1dc127',
'a2ffa8de 3348b3c1 856a429b f97e7e31',
'c2e5bd66'],
['00000118 39296a78 9a3bc004 5c8a5fb4',
'2c7d1bd9 98f54449 579b4468 17afbd17',
'273e662c 97ee7299 5ef42640 c550b901',
'3fad0761 353c7086 a272c240 88be9476',
'9fd16650'],
pre
]
});
}
}
/**
* SECP256K1
* https://www.secg.org/SEC2-Ver-1.0.pdf (page 15, section 2.7.1)
* https://www.secg.org/sec2-v2.pdf (page 9, section 2.4.1)
*/
class SECP256K1 extends ShortCurve {
constructor(pre) {
super({
id: 'SECP256K1',
ossl: 'secp256k1',
type: 'short',
endian: 'be',
hash: 'SHA256',
prime: 'k256',
// 2^256 - 2^32 - 977 (= 3 mod 4)
p: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe fffffc2f'],
a: '0',
b: '7',
n: ['ffffffff ffffffff ffffffff fffffffe',
'baaedce6 af48a03b bfd25e8c d0364141'],
h: '1',
// SVDW
z: '1',
// sqrt(-3)
c: ['0a2d2ba9 3507f1df 233770c2 a797962c',
'c61f6d15 da14ecd4 7d8d27ae 1cd5f852'],
g: [
['79be667e f9dcbbac 55a06295 ce870b07',
'029bfcdb 2dce28d9 59f2815b 16f81798'],
['483ada77 26a3c465 5da4fbfc 0e1108a8',
'fd17b448 a6855419 9c47d08f fb10d4b8'],
pre
],
// Precomputed endomorphism.
endo: {
beta: ['7ae96a2b 657c0710 6e64479e ac3434e9',
'9cf04975 12f58995 c1396c28 719501ee'],
lambda: ['5363ad4c c05c30e0 a5261c02 8812645a',
'122e22ea 20816678 df02967c 1b23bd72'],
basis: [
{
a: '3086d221a7d46bcde86c90e49284eb15',
b: '-e4437ed6010e88286f547fa90abfe4c3'
},
{
a: '114ca50f7a8e2f3f657c1108d9d44cfd8',
b: '3086d221a7d46bcde86c90e49284eb15'
}
],
pre: [
384,
['3086d221 a7d46bcd e86c90e4 9284eb15',
'3daa8a14 71e8ca7f e893209a 45dbb031'],
['-',
'e4437ed6 010e8828 6f547fa9 0abfe4c4',
'221208ac 9df506c6 1571b4ae 8ac47f71']
]
}
});
}
}
/**
* BRAINPOOLP256
* https://tools.ietf.org/html/rfc5639#section-3.4
*/
class BRAINPOOLP256 extends ShortCurve {
constructor(pre) {
super({
id: 'BRAINPOOLP256',
ossl: 'brainpoolP256r1',
type: 'short',
endian: 'be',
hash: 'SHA256',
prime: null,
// (= 3 mod 4)
p: ['a9fb57db a1eea9bc 3e660a90 9d838d72',
'6e3bf623 d5262028 2013481d 1f6e5377'],
a: ['7d5a0975 fc2c3057 eef67530 417affe7',
'fb8055c1 26dc5c6c e94a4b44 f330b5d9'],
b: ['26dc5c6c e94a4b44 f330b5d9 bbd77cbf',
'95841629 5cf7e1ce 6bccdc18 ff8c07b6'],
n: ['a9fb57db a1eea9bc 3e660a90 9d838d71',
'8c397aa3 b561a6f7 901e0e82 974856a7'],
h: '1',
// Icart
z: '-2',
g: [
['8bd2aeb9 cb7e57cb 2c4b482f fc81b7af',
'b9de27e1 e3bd23c2 3a4453bd 9ace3262'],
['547ef835 c3dac4fd 97f8461a 14611dc9',
'c2774513 2ded8e54 5c1d54c7 2f046997'],
pre
]
});
}
}
/**
* BRAINPOOLP384
* https://tools.ietf.org/html/rfc5639#section-3.6
*/
class BRAINPOOLP384 extends ShortCurve {
constructor(pre) {
super({
id: 'BRAINPOOLP384',
ossl: 'brainpoolP384r1',
type: 'short',
endian: 'be',
hash: 'SHA384',
prime: null,
// (= 3 mod 4)
p: ['8cb91e82 a3386d28 0f5d6f7e 50e641df',
'152f7109 ed5456b4 12b1da19 7fb71123',
'acd3a729 901d1a71 87470013 3107ec53'],
a: ['7bc382c6 3d8c150c 3c72080a ce05afa0',
'c2bea28e 4fb22787 139165ef ba91f90f',
'8aa5814a 503ad4eb 04a8c7dd 22ce2826'],
b: ['04a8c7dd 22ce2826 8b39b554 16f0447c',
'2fb77de1 07dcd2a6 2e880ea5 3eeb62d5',
'7cb43902 95dbc994 3ab78696 fa504c11'],
n: ['8cb91e82 a3386d28 0f5d6f7e 50e641df',
'152f7109 ed5456b3 1f166e6c ac0425a7',
'cf3ab6af 6b7fc310 3b883202 e9046565'],
h: '1',
// SSWU
z: '-5',
g: [
['1d1c64f0 68cf45ff a2a63a81 b7c13f6b',
'8847a3e7 7ef14fe3 db7fcafe 0cbd10e8',
'e826e034 36d646aa ef87b2e2 47d4af1e'],
['8abe1d75 20f9c2a4 5cb1eb8e 95cfd552',
'62b70b29 feec5864 e19c054f f9912928',
'0e464621 77918111 42820341 263c5315'],
pre
]
});
}
}
/**
* BRAINPOOLP512
* https://tools.ietf.org/html/rfc5639#section-3.7
*/
class BRAINPOOLP512 extends ShortCurve {
constructor(pre) {
super({
id: 'BRAINPOOLP512',
ossl: 'brainpoolP512r1',
type: 'short',
endian: 'be',
hash: 'SHA512',
prime: null,
// (= 3 mod 4)
p: ['aadd9db8 dbe9c48b 3fd4e6ae 33c9fc07',
'cb308db3 b3c9d20e d6639cca 70330871',
'7d4d9b00 9bc66842 aecda12a e6a380e6',
'2881ff2f 2d82c685 28aa6056 583a48f3'],
a: ['7830a331 8b603b89 e2327145 ac234cc5',
'94cbdd8d 3df91610 a83441ca ea9863bc',
'2ded5d5a a8253aa1 0a2ef1c9 8b9ac8b5',
'7f1117a7 2bf2c7b9 e7c1ac4d 77fc94ca'],
b: ['3df91610 a83441ca ea9863bc 2ded5d5a',
'a8253aa1 0a2ef1c9 8b9ac8b5 7f1117a7',
'2bf2c7b9 e7c1ac4d 77fc94ca dc083e67',
'984050b7 5ebae5dd 2809bd63 8016f723'],
n: ['aadd9db8 dbe9c48b 3fd4e6ae 33c9fc07',
'cb308db3 b3c9d20e d6639cca 70330870',
'553e5c41 4ca92619 41866119 7fac1047',
'1db1d381 085ddadd b5879682 9ca90069'],
h: '1',
// Icart
z: '7',
g: [
['81aee4bd d82ed964 5a21322e 9c4c6a93',
'85ed9f70 b5d916c1 b43b62ee f4d0098e',
'ff3b1f78 e2d0d48d 50d1687b 93b97d5f',
'7c6d5047 406a5e68 8b352209 bcb9f822'],
['7dde385d 566332ec c0eabfa9 cf7822fd',
'f209f700 24a57b1a a000c55b 881f8111',
'b2dcde49 4a5f485e 5bca4bd8 8a2763ae',
'd1ca2b2f a8f05406 78cd1e0f 3ad80892'],
pre
]
});
}
}
/**
* X25519
* https://tools.ietf.org/html/rfc7748#section-4.1
*/
class X25519 extends MontCurve {
constructor() {
super({
id: 'X25519',
ossl: 'X25519',
type: 'mont',
endian: 'le',
hash: 'SHA512',
prime: 'p25519',
// 2^255 - 19 (= 5 mod 8)
p: ['7fffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffed'],
// 486662
a: '76d06',
b: '1',
n: ['10000000 00000000 00000000 00000000',
'14def9de a2f79cd6 5812631a 5cf5d3ed'],
h: '8',
// Elligator 2
z: '2',
g: [
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000009'],
// See: https://www.rfc-editor.org/errata/eid4730
['5f51e65e 475f794b 1fe122d3 88b72eb3',
'6dc2b281 92839e4d d6163a5d 81312c14']
],
torsion: [
[],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000']
],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000001'],
['6be4f497 f9a9c2af c21fa77a d7f4a6ef',
'635a11c7 284a9363 e9a248ef 9c884415']
],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000001'],
['141b0b68 06563d50 3de05885 280b5910',
'9ca5ee38 d7b56c9c 165db710 6377bbd8']
],
[
['57119fd0 dd4e22d8 868e1c58 c45c4404',
'5bef839c 55b1d0b1 248c50a3 bc959c5f'],
['68c59389 3d458e64 31c6ca00 45fb5015',
'20a44346 8eaa68dd 0f103842 048065b7']
],
[
['57119fd0 dd4e22d8 868e1c58 c45c4404',
'5bef839c 55b1d0b1 248c50a3 bc959c5f'],
['173a6c76 c2ba719b ce3935ff ba04afea',
'df5bbcb9 71559722 f0efc7bd fb7f9a36']
],
[
['00b8495f 16056286 fdb1329c eb8d09da',
'6ac49ff1 fae35616 aeb8413b 7c7aebe0'],
['3931c129 569e83a5 29482c14 e628b457',
'933bfc29 ed801b4d 68871483 92507b1a']
],
[
['00b8495f 16056286 fdb1329c eb8d09da',
'6ac49ff1 fae35616 aeb8413b 7c7aebe0'],
['46ce3ed6 a9617c5a d6b7d3eb 19d74ba8',
'6cc403d6 127fe4b2 9778eb7c 6daf84d3']
]
]
});
}
}
/**
* X448
* https://tools.ietf.org/html/rfc7748#section-4.2
*/
class X448 extends MontCurve {
constructor() {
super({
id: 'X448',
ossl: 'X448',
type: 'mont',
endian: 'le',
hash: 'SHAKE256',
prime: 'p448',
// 2^448 - 2^224 - 1 (= 3 mod 4)
p: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff'],
// 156326
a: '262a6',
b: '1',
n: ['3fffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff 7cca23e9',
'c44edb49 aed63690 216cc272 8dc58f55',
'2378c292 ab5844f3'],
h: '4',
// Elligator 2
z: '-1',
g: [
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000005'],
['7d235d12 95f5b1f6 6c98ab6e 58326fce',
'cbae5d34 f55545d0 60f75dc2 8df3f6ed',
'b8027e23 46430d21 1312c4b1 50677af7',
'6fd7223d 457b5b1a']
],
torsion: [
[],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000']
],
[
['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff fffffffe'],
['ba4d3a08 29b6112f 8812e51b a0bb2abe',
'bc1cb08e b48e5569 36ba50fd d2e7d68a',
'f8cb3216 0522425b 3f990812 abbe635a',
'd37a21e1 7551b193']
],
[
['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff fffffffe'],
['45b2c5f7 d649eed0 77ed1ae4 5f44d541',
'43e34f71 4b71aa96 c945af01 2d182975',
'0734cde9 faddbda4 c066f7ed 54419ca5',
'2c85de1e 8aae4e6c']
]
]
});
}
}
/**
* MONT448
* Isomorphic to Ed448-Goldilocks.
*/
class MONT448 extends MontCurve {
constructor() {
super({
id: 'MONT448',
ossl: null,
type: 'mont',
endian: 'le',
hash: 'SHAKE256',
prime: 'p448',
// 2^448 - 2^224 - 1 (= 3 mod 4)
p: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff'],
// -78160 / -39082 mod p
a: ['b2cf97d2 d43459a9 31ed36b1 fc4e3cb5',
'5d93f8d2 22746997 60ccffc6 49961ed6',
'c5b05fca c24864ed 6fb59697 931b78da',
'84ddecd8 ca2b5cfb'],
b: '1',
n: ['3fffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff 7cca23e9',
'c44edb49 aed63690 216cc272 8dc58f55',
'2378c292 ab5844f3'],
h: '4',
// Elligator 2
z: '-1',
g: [
['ac0d24cc c6c75cb0 eb71f81e 7a6edf51',
'48e88aee 009a2a24 e795687e c28e125a',
'3e6730a6 0d46367b aa7fe99d 152128dc',
'41321bc7 7817f059'],
['5a4437f6 80c0d0db 9b061276 d5d0ffcc',
'e786ff33 b6a53d30 98746425 82e66f09',
'4433dae7 7244a6e2 6b11e905 7228f483',
'556c41a5 913f55fe']
],
torsion: [
[],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000']
],
[
['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff fffffffe'],
['bec92fd0 6da2acf2 b4e261e8 7cef0d34',
'22e75c18 3c589857 b71924e5 73c2f9ce',
'e18da5f2 466e2f39 3c2eedf0 f105a60a',
'b40c717d 4f1e1fd7']
],
[
['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff fffffffe'],
['4136d02f 925d530d 4b1d9e17 8310f2cb',
'dd18a3e7 c3a767a8 48e6db19 8c3d0631',
'1e725a0d b991d0c6 c3d1120f 0efa59f5',
'4bf38e82 b0e1e028']
]
]
});
}
}
/**
* ED25519
* https://tools.ietf.org/html/rfc8032#section-5.1
*/
class ED25519 extends EdwardsCurve {
constructor(pre) {
super({
id: 'ED25519',
ossl: 'ED25519',
type: 'edwards',
endian: 'le',
hash: 'SHA512',
prefix: 'SigEd25519 no Ed25519 collisions',
context: false,
prime: 'p25519',
// 2^255 - 19 (= 5 mod 8)
p: ['7fffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffed'],
a: '-1',
// -121665 / 121666 mod p
d: ['52036cee 2b6ffe73 8cc74079 7779e898',
'00700a4d 4141d8ab 75eb4dca 135978a3'],
n: ['10000000 00000000 00000000 00000000',
'14def9de a2f79cd6 5812631a 5cf5d3ed'],
h: '8',
// Elligator 2
z: '2',
g: [
['216936d3 cd6e53fe c0a4e231 fdd6dc5c',
'692cc760 9525a7b2 c9562d60 8f25d51a'],
// 4/5
['66666666 66666666 66666666 66666666',
'66666666 66666666 66666666 66666658'],
pre
],
torsion: [
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000001']
],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000'],
['7fffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff ffffffec']
],
[
['2b832480 4fc1df0b 2b4d0099 3dfbd7a7',
'2f431806 ad2fe478 c4ee1b27 4a0ea0b0'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000']
],
[
['547cdb7f b03e20f4 d4b2ff66 c2042858',
'd0bce7f9 52d01b87 3b11e4d8 b5f15f3d'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000']
],
[
['1fd5b9a0 06394a28 e9339932 38de4abb',
'5c193c70 13e5e238 dea14646 c545d14a'],
['05fc536d 880238b1 3933c6d3 05acdfd5',
'f098eff2 89f4c345 b027b2c2 8f95e826']
],
[
['602a465f f9c6b5d7 16cc66cd c721b544',
'a3e6c38f ec1a1dc7 215eb9b9 3aba2ea3'],
['05fc536d 880238b1 3933c6d3 05acdfd5',
'f098eff2 89f4c345 b027b2c2 8f95e826']
],
[
['1fd5b9a0 06394a28 e9339932 38de4abb',
'5c193c70 13e5e238 dea14646 c545d14a'],
['7a03ac92 77fdc74e c6cc392c fa53202a',
'0f67100d 760b3cba 4fd84d3d 706a17c7']
],
[
['602a465f f9c6b5d7 16cc66cd c721b544',
'a3e6c38f ec1a1dc7 215eb9b9 3aba2ea3'],
['7a03ac92 77fdc74e c6cc392c fa53202a',
'0f67100d 760b3cba 4fd84d3d 706a17c7']
]
]
});
}
}
/**
* ISO448
* https://tools.ietf.org/html/rfc7748#section-4.2
* https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n658
*/
class ISO448 extends EdwardsCurve {
constructor(pre) {
super({
id: 'ISO448',
ossl: null,
type: 'edwards',
endian: 'le',
hash: 'SHAKE256',
prefix: 'SigEd448',
context: true,
prime: 'p448',
// 2^448 - 2^224 - 1 (= 3 mod 4)
p: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff'],
a: '1',
// 39082 / 39081 mod p
d: ['d78b4bdc 7f0daf19 f24f38c2 9373a2cc',
'ad461572 42a50f37 809b1da3 412a12e7',
'9ccc9c81 264cfe9a d0809970 58fb61c4',
'243cc32d baa156b9'],
n: ['3fffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff 7cca23e9',
'c44edb49 aed63690 216cc272 8dc58f55',
'2378c292 ab5844f3'],
h: '4',
// Elligator 2
z: '-1',
g: [
['79a70b2b 70400553 ae7c9df4 16c792c6',
'1128751a c9296924 0c25a07d 728bdc93',
'e21f7787 ed697224 9de732f3 8496cd11',
'69871309 3e9c04fc'],
// Note: the RFC has this wrong.
['7fffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff 80000000',
'00000000 00000000 00000000 00000000',
'00000000 00000001'],
pre
],
torsion: [
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000001']
],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000'],
['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff fffffffe']
],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000001'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000']
],
[
['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff fffffffe'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000']
]
]
});
}
}
/**
* ED448
* https://tools.ietf.org/html/rfc8032#section-5.2
*/
class ED448 extends EdwardsCurve {
constructor(pre) {
super({
id: 'ED448',
ossl: 'ED448',
type: 'edwards',
endian: 'le',
hash: 'SHAKE256',
prefix: 'SigEd448',
context: true,
prime: 'p448',
// 2^448 - 2^224 - 1 (= 3 mod 4)
p: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff'],
a: '1',
// -39081 mod p
d: ['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffff6756'],
n: ['3fffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff ffffffff 7cca23e9',
'c44edb49 aed63690 216cc272 8dc58f55',
'2378c292 ab5844f3'],
h: '4',
// Elligator 2
z: '-1',
g: [
['4f1970c6 6bed0ded 221d15a6 22bf36da',
'9e146570 470f1767 ea6de324 a3d3a464',
'12ae1af7 2ab66511 433b80e1 8b00938e',
'2626a82b c70cc05e'],
['693f4671 6eb6bc24 88762037 56c9c762',
'4bea7373 6ca39840 87789c1e 05a0c2d7',
'3ad3ff1c e67c39c4 fdbd132c 4ed7c8ad',
'9808795b f230fa14'],
pre
],
torsion: [
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000001']
],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000'],
['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff fffffffe']
],
[
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000001'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000']
],
[
['ffffffff ffffffff ffffffff ffffffff',
'ffffffff ffffffff fffffffe ffffffff',
'ffffffff ffffffff ffffffff ffffffff',
'ffffffff fffffffe'],
['00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000 00000000 00000000',
'00000000 00000000']
]
]
});
}
}
/*
* Curve Registry
*/
const curves = {
__proto__: null,
P192,
P224,
P256,
P384,
P521,
SECP256K1,
BRAINPOOLP256,
BRAINPOOLP384,
BRAINPOOLP512,
X25519,
X448,
MONT448,
ED25519,
ISO448,
ED448
};
const cache = {
__proto__: null,
P192: null,
P224: null,
P256: null,
P384: null,
P521: null,
SECP256K1: null,
BRAINPOOLP256: null,
BRAINPOOLP384: null,
BRAINPOOLP512: null,
X25519: null,
X448: null,
MONT448: null,
ED25519: null,
ISO448: null,
ED448: null
};
function curve(name, ...args) {
assert(typeof name === 'string');
const key = name.toUpperCase();
let curve = cache[key];
if (!curve) {
const Curve = curves[key];
if (!Curve)
throw new Error(`Curve not found: "${name}".`);
curve = new Curve(...args);
cache[key] = curve;
}
return curve;
}
function register(name, Curve) {
assert(typeof name === 'string');
assert(typeof Curve === 'function');
const key = name.toUpperCase();
if (curves[key])
throw new Error(`Curve already registered: "${name}".`);
curves[key] = Curve;
cache[key] = null;
}
/*
* Scalar Recoding
*/
function getNAF(k, width, max) {
// Computing the width-w NAF of a positive integer.
//
// [GECC] Algorithm 3.35, Page 100, Section 3.3.
//
// The above document describes a rather abstract
// method of recoding. The more optimal method
// below was ported from libsecp256k1.
assert(k instanceof BN);
assert(!k.red);
assert((width >>> 0) === width);
assert((max >>> 0) === max);
const naf = new Array(max);
const bits = k.bitLength() + 1;
const sign = k.sign() | 1;
assert(bits <= max);
for (let i = 0; i < max; i++)
naf[i] = 0;
let i = 0;
let carry = 0;
let word;
while (i < bits) {
if (k.bit(i) === carry) {
i += 1;
continue;
}
word = k.bits(i, width) + carry;
carry = (word >> (width - 1)) & 1;
word -= carry << width;
naf[i] = sign * word;
i += width;
}
assert(carry === 0);
return naf;
}
function getFixedNAF(k, width, max, step) {
assert((step >>> 0) === step);
// Recode to NAF.
const naf = getNAF(k, width, max);
// Translate into more windowed form.
const len = Math.ceil(naf.length / step);
const repr = new Array(len);
let i = 0;
for (let j = 0; j < naf.length; j += step) {
let nafW = 0;
for (let k = j + step - 1; k >= j; k--)
nafW = (nafW << 1) + naf[k];
repr[i++] = nafW;
}
assert(i === len);
return repr;
}
function getJSF(k1, k2, max) {
// Joint sparse form.
//
// [GECC] Algorithm 3.50, Page 111, Section 3.3.
assert(k1 instanceof BN);
assert(k2 instanceof BN);
assert(!k1.red);
assert(!k2.red);
assert((max >>> 0) === max);
const jsf = [new Array(max), new Array(max)];
const bits = Math.max(k1.bitLength(), k2.bitLength()) + 1;
const s1 = k1.sign() | 1;
const s2 = k2.sign() | 1;
assert(bits <= max);
let d1 = 0;
let d2 = 0;
for (let i = 0; i < bits; i++) {
const b1 = k1.bits(i, 3);
const b2 = k2.bits(i, 3);
// First phase.
let m14 = ((b1 & 3) + d1) & 3;
let m24 = ((b2 & 3) + d2) & 3;
let u1 = 0;
let u2 = 0;
if (m14 === 3)
m14 = -1;
if (m24 === 3)
m24 = -1;
if (m14 & 1) {
const m8 = ((b1 & 7) + d1) & 7;
if ((m8 === 3 || m8 === 5) && m24 === 2)
u1 = -m14;
else
u1 = m14;
}
if (m24 & 1) {
const m8 = ((b2 & 7) + d2) & 7;
if ((m8 === 3 || m8 === 5) && m14 === 2)
u2 = -m24;
else
u2 = m24;
}
jsf[0][i] = u1 * s1;
jsf[1][i] = u2 * s2;
// Second phase.
if (2 * d1 === 1 + u1)
d1 = 1 - d1;
if (2 * d2 === 1 + u2)
d2 = 1 - d2;
}
for (let i = bits; i < max; i++) {
jsf[0][i] = 0;
jsf[1][i] = 0;
}
return jsf;
}
function getJNAF(c1, c2, max) {
const jsf = getJSF(c1, c2, max);
const naf = new Array(max);
// JSF -> NAF conversion.
for (let i = 0; i < max; i++) {
const ja = jsf[0][i];
const jb = jsf[1][i];
naf[i] = jsfIndex[(ja + 1) * 3 + (jb + 1)];
}
return naf;
}
/*
* Helpers
*/
function assert(val, msg) {
if (!val) {
const err = new Error(msg || 'Assertion failed');
if (Error.captureStackTrace)
Error.captureStackTrace(err, assert);
throw err;
}
}
function wrapErrors(fn) {
assert(typeof fn === 'function');
try {
return fn();
} catch (e) {
if (e.message === 'X is not a square mod P.'
|| e.message === 'Not invertible.') {
throw new Error('Invalid point.');
}
throw e;
}
}
function mod(x, y) {
// Euclidean modulo.
let r = x % y;
if (r < 0) {
if (y < 0)
r -= y;
else
r += y;
}
return r;
}
function cubeRoot(x) {
assert(x instanceof BN);
assert(x.red);
const p = x.red.m;
if (p.cmpn(3) <= 0)
return x.clone();
// p = 2 mod 3
if (p.modrn(3) === 2) {
// e = (2 * p - 1) / 3
const e = p.ushln(1).isubn(1).idivn(3);
return x.redPow(e);
}
const mod9 = p.modrn(9);
// p = 4 mod 9
if (mod9 === 4) {
// e = (2 * p + 1) / 9
const e = p.ushln(1).iaddn(1).idivn(9);
const r = x.redPow(e);
const c = r.redSqr().redMul(r);
if (!c.eq(x))
throw new Error('X is not a cube mod P.');
return r;
}
// p = 7 mod 9
if (mod9 === 7) {
// e = (p + 2) / 9
const e = p.addn(2).idivn(9);
const r = x.redPow(e);
const c = r.redSqr().redMul(r);
if (!c.eq(x))
throw new Error('X is not a cube mod P.');
return r;
}
throw new Error('Not implemented.');
}
function cubeRoots(x) {
const r0 = cubeRoot(x);
// p = 1 mod 3
if (x.red.m.modrn(3) === 1) {
// Multiply by roots of unity to find other roots.
const two = new BN(2).toRed(x.red);
const three = new BN(3).toRed(x.red);
const i2 = two.redInvert();
const s1 = three.redNeg().redSqrt().redMul(i2);
const s2 = s1.redNeg();
const u1 = s1.redSub(i2);
const u2 = s2.redSub(i2);
const r1 = r0.redMul(u1);
const r2 = r0.redMul(u2);
return [r0, r1, r2];
}
// p = 2 mod 3 guarantees 1 cube root per element.
return [r0];
}
function uncube(x) {
// Find a cube root which is also a quadratic residue.
for (const root of cubeRoots(x)) {
if (root.redJacobi() >= 0)
return root;
}
throw new Error('X^(1/3) is not a square mod P.');
}
function randomInt(rng) {
return BN.randomBits(rng, 32).toNumber();
}
function memoize(method, self) {
const cache = new WeakMap();
return function memoized(curve, invert) {
const i = invert & 1;
const item = cache.get(curve);
if (item && item[i] !== null)
return item[i];
const result = method.call(self, curve, invert);
if (!cache.has(curve))
cache.set(curve, [null, null]);
cache.get(curve)[i] = result;
return result;
};
}
function toPretty(x, size) {
assert(x instanceof BN);
assert((size >>> 0) === size);
if (size & 7)
size += 8 - (size & 7);
const str = x.toString(16, size);
const chunks = [];
const out = [];
assert((str.length & 7) === 0);
for (let i = 0; i < str.length; i += 8)
chunks.push(str.slice(i, i + 8));
for (let i = 0; i < chunks.length; i += 4)
out.push(chunks.slice(i, i + 4).join(' '));
return out;
}
/*
* Expose
*/
exports.Curve = Curve;
exports.Point = Point;
exports.ShortCurve = ShortCurve;
exports.ShortPoint = ShortPoint;
exports.JPoint = JPoint;
exports.MontCurve = MontCurve;
exports.MontPoint = MontPoint;
exports.XPoint = XPoint;
exports.EdwardsCurve = EdwardsCurve;
exports.EdwardsPoint = EdwardsPoint;
exports.curves = curves;
exports.curve = curve;
exports.register = register;
}],
[/* 43 */ 'bcrypto', '/lib/js/precomputed/secp256k1.json', function(exports, module, __filename, __dirname, __meta) {
module.exports = {
"naf": {
"width": 9,
"points": [
[
"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
"388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"
],
[
"2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4",
"d8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6"
],
[
"5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc",
"6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da"
],
[
"acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe",
"cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37"
],
[
"774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb",
"d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b"
],
[
"f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8",
"0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"
],
[
"d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e",
"581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58"
],
[
"defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34",
"4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"
],
[
"2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c",
"85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"
],
[
"352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5",
"321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"
],
[
"2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f",
"02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"
],
[
"9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714",
"73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"
],
[
"daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729",
"a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"
],
[
"c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db",
"2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"
],
[
"6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4",
"e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"
],
[
"1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5",
"b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396"
],
[
"605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479",
"02972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49"
],
[
"62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d",
"80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf"
],
[
"80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f",
"1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a"
],
[
"7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb",
"0d0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7"
],
[
"d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9",
"eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933"
],
[
"049370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963",
"758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a"
],
[
"77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74",
"958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6"
],
[
"f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530",
"e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37"
],
[
"463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b",
"5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e"
],
[
"f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247",
"cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6"
],
[
"caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1",
"cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476"
],
[
"2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120",
"4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40"
],
[
"7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435",
"091b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61"
],
[
"754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18",
"0673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683"
],
[
"e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8",
"59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5"
],
[
"186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb",
"3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b"
],
[
"df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f",
"55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417"
],
[
"5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143",
"efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868"
],
[
"290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba",
"e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a"
],
[
"af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45",
"f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6"
],
[
"766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a",
"744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996"
],
[
"59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e",
"c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e"
],
[
"f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8",
"e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d"
],
[
"7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c",
"30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2"
],
[
"948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519",
"e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e"
],
[
"7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab",
"100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437"
],
[
"3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca",
"ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311"
],
[
"d3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf",
"8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4"
],
[
"1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610",
"68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575"
],
[
"733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4",
"f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d"
],
[
"15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c",
"d56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d"
],
[
"a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940",
"edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629"
],
[
"e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980",
"0a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06"
],
[
"311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3",
"66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374"
],
[
"34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf",
"09414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee"
],
[
"f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63",
"4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1"
],
[
"d7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448",
"fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b"
],
[
"32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf",
"5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661"
],
[
"7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5",
"8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6"
],
[
"ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6",
"8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e"
],
[
"16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5",
"5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d"
],
[
"eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99",
"f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc"
],
[
"078c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51",
"f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4"
],
[
"494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5",
"42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c"
],
[
"a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5",
"204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b"
],
[
"c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997",
"04f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913"
],
[
"841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881",
"073867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154"
],
[
"5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5",
"39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865"
],
[
"36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66",
"d2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc"
],
[
"0336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726",
"ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224"
],
[
"8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede",
"6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e"
],
[
"1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94",
"060660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6"
],
[
"85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31",
"3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511"
],
[
"29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51",
"0b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b"
],
[
"a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252",
"ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2"
],
[
"04e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5",
"cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c"
],
[
"d24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b",
"6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3"
],
[
"ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4",
"322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d"
],
[
"af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f",
"6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700"
],
[
"e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889",
"2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4"
],
[
"591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246",
"b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196"
],
[
"11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984",
"998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4"
],
[
"3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a",
"b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257"
],
[
"cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030",
"bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13"
],
[
"c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197",
"6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096"
],
[
"0c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593",
"c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38"
],
[
"a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef",
"021ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f"
],
[
"347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38",
"60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448"
],
[
"da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a",
"49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a"
],
[
"c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111",
"5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4"
],
[
"4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502",
"7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437"
],
[
"3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea",
"be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7"
],
[
"cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26",
"8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d"
],
[
"b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986",
"39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a"
],
[
"d4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e",
"62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54"
],
[
"48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4",
"25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77"
],
[
"dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda",
"ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517"
],
[
"6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859",
"cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10"
],
[
"e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f",
"f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125"
],
[
"eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c",
"6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e"
],
[
"13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942",
"fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1"
],
[
"ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a",
"1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2"
],
[
"b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80",
"5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423"
],
[
"ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d",
"438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8"
],
[
"8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1",
"cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758"
],
[
"52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63",
"0c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375"
],
[
"e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352",
"6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d"
],
[
"7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193",
"ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec"
],
[
"5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00",
"09731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0"
],
[
"32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58",
"ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c"
],
[
"e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7",
"d3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4"
],
[
"8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8",
"c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f"
],
[
"4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e",
"67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649"
],
[
"3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d",
"0cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826"
],
[
"674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b",
"299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5"
],
[
"d32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f",
"f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87"
],
[
"30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6",
"462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b"
],
[
"be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297",
"62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc"
],
[
"93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a",
"7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c"
],
[
"b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c",
"ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f"
],
[
"d5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52",
"4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a"
],
[
"d3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb",
"bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46"
],
[
"463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065",
"bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f"
],
[
"7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917",
"603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03"
],
[
"74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
"cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08"
],
[
"30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3",
"553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8"
],
[
"9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57",
"0712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373"
],
[
"176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66",
"ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3"
],
[
"75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8",
"9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8"
],
[
"809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721",
"9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1"
],
[
"1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180",
"4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9"
]
]
},
"doubles": {
"step": 4,
"points": [
[
"e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a",
"f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"
],
[
"8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508",
"11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf"
],
[
"175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739",
"d3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695"
],
[
"363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
"04e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9"
],
[
"8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c",
"4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36"
],
[
"723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda",
"96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f"
],
[
"eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa",
"5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999"
],
[
"100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0",
"cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09"
],
[
"e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d",
"9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d"
],
[
"feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d",
"e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088"
],
[
"da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1",
"9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d"
],
[
"53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0",
"5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8"
],
[
"8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047",
"10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a"
],
[
"385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862",
"283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453"
],
[
"06f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7",
"7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160"
],
[
"3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd",
"56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0"
],
[
"85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83",
"7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6"
],
[
"0948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a",
"53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589"
],
[
"6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8",
"bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17"
],
[
"e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d",
"4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda"
],
[
"e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725",
"7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd"
],
[
"213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754",
"4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2"
],
[
"4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c",
"17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6"
],
[
"fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6",
"6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f"
],
[
"76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39",
"c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01"
],
[
"c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891",
"893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3"
],
[
"d895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b",
"febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f"
],
[
"b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03",
"2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7"
],
[
"e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d",
"eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78"
],
[
"a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070",
"7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1"
],
[
"90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4",
"0e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150"
],
[
"8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da",
"662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82"
],
[
"e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11",
"1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc"
],
[
"8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e",
"efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b"
],
[
"e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41",
"2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51"
],
[
"b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef",
"067c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45"
],
[
"d68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8",
"db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120"
],
[
"324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d",
"648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84"
],
[
"4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96",
"35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d"
],
[
"9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd",
"ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d"
],
[
"6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5",
"9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8"
],
[
"a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266",
"40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8"
],
[
"7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71",
"34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac"
],
[
"0928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac",
"c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f"
],
[
"85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751",
"1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962"
],
[
"ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e",
"493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907"
],
[
"827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241",
"c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec"
],
[
"eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3",
"be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d"
],
[
"e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f",
"4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414"
],
[
"1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19",
"aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd"
],
[
"146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be",
"b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0"
],
[
"fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9",
"6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811"
],
[
"da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2",
"8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1"
],
[
"a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13",
"7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c"
],
[
"174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c",
"ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73"
],
[
"959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba",
"2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd"
],
[
"d2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151",
"e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405"
],
[
"64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073",
"d99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589"
],
[
"8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458",
"38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e"
],
[
"13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b",
"69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27"
],
[
"bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366",
"0d3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1"
],
[
"8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa",
"40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482"
],
[
"08ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0",
"620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945"
],
[
"dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787",
"7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573"
],
[
"f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e",
"ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82"
]
]
}
};
}],
[/* 44 */ 'hsd', '/lib/protocol/network.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* network.js - network object for hsd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
'use strict';
const assert = __node_require__(2 /* 'bsert' */);
const binary = __node_require__(45 /* '../utils/binary' */);
const networks = __node_require__(46 /* './networks' */);
const TimeData = __node_require__(49 /* './timedata' */);
/**
* Network
* Represents a network.
* @alias module:protocol.Network
*/
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.brontidePort = options.brontidePort;
this.checkpointMap = options.checkpointMap;
this.lastCheckpoint = options.lastCheckpoint;
this.checkpoints = [];
this.halvingInterval = options.halvingInterval;
this.coinbaseMaturity = options.coinbaseMaturity;
this.genesis = options.genesis;
this.genesisBlock = options.genesisBlock;
this.pow = options.pow;
this.names = options.names;
this.goosigStop = options.goosigStop;
this.block = options.block;
this.activationThreshold = options.activationThreshold;
this.minerWindow = options.minerWindow;
this.deployments = options.deployments;
this.deploys = options.deploys;
this.unknownBits = 0;
this.keyPrefix = options.keyPrefix;
this.addressPrefix = options.addressPrefix;
this.requireStandard = options.requireStandard;
this.rpcPort = options.rpcPort;
this.walletPort = options.walletPort;
this.nsPort = options.nsPort;
this.rsPort = options.rsPort;
this.minRelay = options.minRelay;
this.feeRate = options.feeRate;
this.maxFeeRate = options.maxFeeRate;
this.identityKey = options.identityKey;
this.selfConnect = options.selfConnect;
this.requestMempool = options.requestMempool;
this.claimPrefix = options.claimPrefix;
this.deflationHeight = options.deflationHeight;
this.time = new TimeData();
this.txStart = options.txStart;
this.init();
}
/**
* Get a deployment by bit index.
* @param {Number} bit
* @returns {Object}
*/
init() {
let bits = 0;
for (const deployment of this.deploys)
bits |= 1 << deployment.bit;
this.unknownBits = ~bits >>> 0;
for (const key of Object.keys(this.checkpointMap)) {
const hash = this.checkpointMap[key];
const height = Number(key);
this.checkpoints.push({ hash, height });
}
this.checkpoints.sort(cmpNode);
}
/**
* Get a deployment by bit index.
* @param {Number} bit
* @returns {Object}
*/
byBit(bit) {
const index = binary.search(this.deploys, bit, cmpBit);
if (index === -1)
return null;
return this.deploys[index];
}
/**
* Get network adjusted time.
* @returns {Number}
*/
now() {
return this.time.now();
}
/**
* Get network adjusted time in milliseconds.
* @returns {Number}
*/
ms() {
return this.time.ms();
}
/**
* Create a network. Get existing network if possible.
* @param {NetworkType|Object} options
* @returns {Network}
*/
static create(options) {
if (typeof options === 'string')
options = networks[options];
assert(options, 'Unknown network.');
if (Network[options.type])
return Network[options.type];
const network = new Network(options);
Network[network.type] = network;
if (!Network.primary)
Network.primary = network;
return network;
}
/**
* 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;
}
/**
* Get a network with a string or a Network object.
* @param {NetworkType|Network} type - Network type.
* @returns {Network}
*/
static get(type) {
if (!type) {
assert(Network.primary, 'No default network.');
return Network.primary;
}
if (type instanceof Network)
return type;
if (typeof type === 'string')
return Network.create(type);
throw new Error('Unknown network.');
}
/**
* Get a network with a string or a Network object.
* @param {NetworkType|Network} type - Network type.
* @returns {Network}
*/
static ensure(type) {
if (!type) {
assert(Network.primary, 'No default network.');
return Network.primary;
}
if (type instanceof Network)
return type;
if (typeof type === 'string') {
if (networks[type])
return Network.create(type);
}
assert(Network.primary, 'No default network.');
return Network.primary;
}
/**
* 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}.`);
}
/**
* Get a network by its magic number.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
static fromMagic(value, network) {
return Network.by(value, cmpMagic, network, 'magic number');
}
/**
* Get a network by its WIF prefix.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
static fromWIF(prefix, network) {
return Network.by(prefix, cmpWIF, network, 'WIF');
}
/**
* Get a network by its xpubkey prefix.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
static fromPublic(prefix, network) {
return Network.by(prefix, cmpPub, network, 'xpubkey');
}
/**
* Get a network by its xprivkey prefix.
* @param {Number} value
* @param {Network?} network
* @returns {Network}
*/
static fromPrivate(prefix, network) {
return Network.by(prefix, cmpPriv, network, 'xprivkey');
}
/**
* Get a network by its xpubkey base58 prefix.
* @param {String} prefix
* @param {Network?} network
* @returns {Network}
*/
static fromPublic58(prefix, network) {
return Network.by(prefix, cmpPub58, network, 'xpubkey');
}
/**
* Get a network by its xprivkey base58 prefix.
* @param {String} prefix
* @param {Network?} network
* @returns {Network}
*/
static fromPrivate58(prefix, network) {
return Network.by(prefix, cmpPriv58, network, 'xprivkey');
}
/**
* Get a network by its bech32 address prefix.
* @param {String} hrp
* @param {Network?} network
* @returns {Network}
*/
static fromAddress(hrp, network) {
return Network.by(hrp, cmpAddress, network, 'address');
}
/**
* Convert the network to a string.
* @returns {String}
*/
toString() {
return this.type;
}
/**
* Inspect the network.
* @returns {String}
*/
inspect() {
return `<Network: ${this.type}>`;
}
/**
* Test an object to see if it is a Network.
* @param {Object} obj
* @returns {Boolean}
*/
static isNetwork(obj) {
return obj instanceof Network;
}
}
/**
* Default network.
* @type {Network}
*/
Network.primary = null;
/**
* Default network type.
* @type {String}
*/
Network.type = null;
/*
* Networks (to avoid hash table mode).
*/
Network.main = null;
Network.testnet = null;
Network.regtest = null;
Network.segnet4 = null;
Network.simnet = null;
/*
* Set initial network.
*/
Network.set(process.env.HSD_NETWORK || 'main');
/*
* Helpers
*/
function cmpBit(a, b) {
return a.bit - b;
}
function cmpNode(a, b) {
return a.height - b.height;
}
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, hrp) {
return network.addressPrefix === hrp;
}
/*
* Expose
*/
module.exports = Network;
}],
[/* 45 */ 'hsd', '/lib/utils/binary.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* binary.js - binary search utils for hsd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
'use strict';
/**
* Perform a binary search on a sorted array.
* @param {Array} items
* @param {Object} key
* @param {Function} compare
* @param {Boolean?} insert
* @returns {Number} Index.
*/
exports.search = function search(items, key, compare, insert) {
let start = 0;
let end = items.length - 1;
while (start <= end) {
const pos = (start + end) >>> 1;
const cmp = compare(items[pos], key);
if (cmp === 0)
return pos;
if (cmp < 0)
start = pos + 1;
else
end = pos - 1;
}
if (!insert)
return -1;
return start;
};
/**
* Perform a binary insert on a sorted array.
* @param {Array} items
* @param {Object} item
* @param {Function} compare
* @returns {Number} index
*/
exports.insert = function insert(items, item, compare, uniq) {
const i = exports.search(items, item, compare, true);
if (uniq && i < items.length) {
if (compare(items[i], item) === 0)
return -1;
}
if (i === 0)
items.unshift(item);
else if (i === items.length)
items.push(item);
else
items.splice(i, 0, item);
return i;
};
/**
* Perform a binary removal on a sorted array.
* @param {Array} items
* @param {Object} item
* @param {Function} compare
* @returns {Boolean}
*/
exports.remove = function remove(items, item, compare) {
const i = exports.search(items, item, compare, false);
if (i === -1)
return false;
splice(items, i);
return true;
};
/*
* Helpers
*/
function splice(list, i) {
if (i === 0) {
list.shift();
return;
}
let k = i + 1;
while (k < list.length)
list[i++] = list[k++];
list.pop();
}
}],
[/* 46 */ 'hsd', '/lib/protocol/networks.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* network.js - handshake networks for hsd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
/* eslint no-implicit-coercion: "off" */
'use strict';
/**
* @module protocol/networks
*/
const BN = __node_require__(31 /* 'bcrypto/lib/bn.js' */);
const genesis = __node_require__(47 /* './genesis' */);
const network = exports;
/**
* Network type list.
* @memberof module:protocol/networks
* @const {String[]}
* @default
*/
network.types = ['main', 'testnet', 'regtest', 'simnet'];
/**
* Mainnet
* @static
* @lends module:protocol/networks
* @type {Object}
*/
const main = {};
/**
* Symbolic network type.
* @const {String}
* @default
*/
main.type = 'main';
/**
* Default DNS seeds.
* @const {String[]}
* @default
*/
main.seeds = [
'hs-mainnet.bcoin.ninja', // Christopher Jeffrey
'seed.easyhandshake.com' // Matthew Zipkin
];
/**
* Packet magic number.
* @const {Number}
* @default
*/
main.magic = genesis.main.magic;
/**
* Default network port.
* @const {Number}
* @default
*/
main.port = 12038;
/**
* Default brontide port.
* @const {Number}
* @default
*/
main.brontidePort = 44806;
/**
* Checkpoint block list.
* @const {Object}
*/
main.checkpointMap = {
1008: Buffer.from(
'0000000000001013c28fa079b545fb805f04c496687799b98e35e83cbbb8953e', 'hex'),
2016: Buffer.from(
'0000000000000424ee6c2a5d6e0da5edfc47a4a10328c1792056ee48303c3e40', 'hex'),
10000: Buffer.from(
'00000000000001a86811a6f520bf67cefa03207dc84fd315f58153b28694ec51', 'hex'),
20000: Buffer.from(
'0000000000000162c7ac70a582256f59c189b5c90d8e9861b3f374ed714c58de', 'hex'),
30000: Buffer.from(
'0000000000000004f790862846b23c3a81585aea0fa79a7d851b409e027bcaa7', 'hex'),
40000: Buffer.from(
'0000000000000002966206a40b10a575cb46531253b08dae8e1b356cfa277248', 'hex'),
50000: Buffer.from(
'00000000000000020c7447e7139feeb90549bfc77a7f18d4ff28f327c04f8d6e', 'hex'),
56880: Buffer.from(
'0000000000000001d4ef9ea6908bb4eb970d556bd07cbd7d06a634e1cd5bbf4e', 'hex'),
61043: Buffer.from(
'00000000000000015b84385e0307370f8323420eaa27ef6e407f2d3162f1fd05', 'hex')
};
/**
* Last checkpoint height.
* @const {Number}
* @default
*/
main.lastCheckpoint = 61043;
/**
* Reward halving interval.
* Roughly every 3.25 years.
* @const {Number}
* @default
*/
main.halvingInterval = 170000;
/**
* Number of blocks before a coinbase
* spend can occur (consensus).
* @const {Number}
* @default
*/
main.coinbaseMaturity = 100;
/**
* Genesis block header.
* @const {Object}
*/
main.genesis = genesis.main;
/**
* The network's genesis block in a hex string.
* @const {String}
*/
main.genesisBlock = genesis.mainData;
/**
* POW-related constants.
* @enum {Number}
* @default
*/
main.pow = {};
/**
* Default target.
* @const {BN}
*/
main.pow.limit = new BN(
'0000000000ffff00000000000000000000000000000000000000000000000000',
'hex'
);
/**
* Compact pow limit.
* @const {Number}
* @default
*/
main.pow.bits = 0x1c00ffff;
/**
* Minimum chainwork for best chain.
* @const {BN}
*/
main.pow.chainwork = new BN(
'00000000000000000000000000000000000000000000000075b5a2b7bf522d45',
'hex'
);
/**
* Retarget window in blocks.
* @const {Number}
* @default
*/
main.pow.targetWindow = 144;
/**
* Average block time.
* @const {Number}
* @default
*/
main.pow.targetSpacing = 10 * 60;
/**
* Average blocks per day.
* @const {Number}
* @default
*/
main.pow.blocksPerDay = ((24 * 60 * 60) / main.pow.targetSpacing) >>> 0;
/**
* Desired retarget period in seconds.
* @const {Number}
* @default
*/
main.pow.targetTimespan = main.pow.targetWindow * main.pow.targetSpacing;
/**
* Minimum actual time.
* @const {Number}
* @default
*/
main.pow.minActual = (main.pow.targetTimespan / 4) >>> 0;
/**
* Maximum actual time.
* @const {Number}
* @default
*/
main.pow.maxActual = main.pow.targetTimespan * 4;
/**
* Whether to reset target if a block
* has not been mined recently.
* @const {Boolean}
* @default
*/
main.pow.targetReset = false;
/**
* Do not allow retargetting.
* @const {Boolean}
* @default
*/
main.pow.noRetargeting = false;
/**
* Prohibit all transactions until
* sufficient chainwork has been accumulated.
* @const {Number}
*/
main.txStart = 14 * main.pow.blocksPerDay;
/**
* Name-related constants.
* @enum {Number}
* @default
*/
main.names = {
/**
* Height at which the auction system activates.
* Must be greater or equal to txStart.
* @const {Number}
*/
auctionStart: 14 * main.pow.blocksPerDay,
/**
* Interval at which names are rolled out.
* @const {Number}
*/
rolloutInterval: 7 * main.pow.blocksPerDay,
/**
* Amount of time a name is locked for after being claimed.
* @const {Number}
*/
lockupPeriod: 30 * main.pow.blocksPerDay,
/**
* Time period after which names expire.
* @const {Number}
*/
renewalWindow: (2 * 365) * main.pow.blocksPerDay,
/**
* Committed renewal block hashes
* must be no older than this.
* @const {Number}
*/
renewalPeriod: 182 * main.pow.blocksPerDay,
/**
* Committed renewal block hashes
* must be at least this old.
* @const {Number}
*/
renewalMaturity: 30 * main.pow.blocksPerDay,
/**
* The time window in which the
* nameholders can claim reserved names.
* @const {Number}
*/
claimPeriod: (4 * 365) * main.pow.blocksPerDay,
/**
* Amount of time required in between
* replacement claims.
* @const {Number}
*/
claimFrequency: 2 * main.pow.blocksPerDay,
/**
* Bidding time period.
* @const {Number}
*/
biddingPeriod: 5 * main.pow.blocksPerDay,
/**
* Reveal time period.
* @const {Number}
*/
revealPeriod: 10 * main.pow.blocksPerDay,
/**
* Interval at which the name tree is updated.
* @const {Number}
*/
treeInterval: main.pow.blocksPerDay >>> 2,
/**
* Amount of time transfers are locked up for.
* @const {Number}
*/
transferLockup: 2 * main.pow.blocksPerDay,
/**
* Amount of time before a transfer
* or revocation is possible.
* @const {Number}
*/
revocationDelay: 14 * main.pow.blocksPerDay,
/**
* Sum of total period and revocation delay.
* @const {Number}
*/
auctionMaturity: (5 + 10 + 14) * main.pow.blocksPerDay,
/**
* Whether there is no weekly rollout.
* @const {Boolean}
*/
noRollout: false,
/**
* Whether there are no names reserved.
* @const {Boolean}
*/
noReserved: false
};
/**
* Block constants.
* @enum {Number}
* @default
*/
main.block = {
/**
* Safe height to start pruning.
*/
pruneAfterHeight: 1000,
/**
* Safe number of blocks to keep.
*/
keepBlocks: 288,
/**
* Age used for the time delta to
* determine whether the chain is synced.
*/
maxTipAge: 12 * 60 * 60,
/**
* Height at which block processing is
* slow enough that we can output
* logs without spamming.
*/
slowHeight: 0
};
/**
* Block height at which GooSig claims are
* disabled. This limits risk associated
* with newly discovered cryptography
* attacks or social engineering attacks.
*
* Estimated to be disabled at 1 year +
* 1 month from the start of the network
* on mainnet.
*/
main.goosigStop = (365 + 30) * main.pow.blocksPerDay;
/**
* For versionbits.
* @const {Number}
* @default
*/
main.activationThreshold = 1916;
/**
* Confirmation window for versionbits.
* @const {Number}
* @default
*/
main.minerWindow = 2016;
/**
* Deployments for versionbits.
* @const {Object}
* @default
*/
main.deployments = {
hardening: {
name: 'hardening',
bit: 0,
startTime: 1581638400, // February 14th, 2020
timeout: 1707868800, // February 14th, 2024
threshold: -1,
window: -1,
required: false,
force: false
},
testdummy: {
name: 'testdummy',
bit: 28,
startTime: 1199145601, // January 1, 2008
timeout: 1230767999, // December 31, 2008
threshold: -1,
window: -1,
required: false,
force: true
}
};
/**
* Deployments for versionbits (array form, sorted).
* @const {Array}
* @default
*/
main.deploys = [
main.deployments.hardening,
main.deployments.testdummy
];
/**
* Key prefixes.
* @enum {Number}
* @default
*/
main.keyPrefix = {
privkey: 0x80,
xpubkey: 0x0488b21e,
xprivkey: 0x0488ade4,
xpubkey58: 'xpub',
xprivkey58: 'xprv',
coinType: 5353
};
/**
* Address prefix.
* @const {String}
*/
main.addressPrefix = 'hs';
/**
* Default value for whether the mempool
* accepts non-standard transactions.
* @const {Boolean}
* @default
*/
main.requireStandard = true;
/**
* Default http port.
* @const {Number}
* @default
*/
main.rpcPort = 12037;
/**
* Default wallet port.
* @const {Number}
* @default
*/
main.walletPort = 12039;
/**
* Default DNS port.
* @const {Number}
* @default
*/
main.nsPort = 5349;
/**
* Default recursive DNS port.
* @const {Number}
* @default
*/
main.rsPort = 5350;
/**
* Default min relay rate.
* @const {Rate}
* @default
*/
main.minRelay = 1000;
/**
* Default normal relay rate.
* @const {Rate}
* @default
*/
main.feeRate = 100000;
/**
* Maximum normal relay rate.
* @const {Rate}
* @default
*/
main.maxFeeRate = 400000;
/**
* Default identity key (testing only).
* @const {Buffer|null}
* @default
*/
main.identityKey = null;
/**
* Whether to allow self-connection.
* @const {Boolean}
*/
main.selfConnect = false;
/**
* Whether to request mempool on sync.
* @const {Boolean}
*/
main.requestMempool = false;
/**
* DNSSEC ownership prefix.
* @const {String}
*/
main.claimPrefix = 'hns-claim:';
/**
* Activation height for inflation bug fix.
* @const {Number}
*/
main.deflationHeight = 61043;
/*
* Testnet
*/
const testnet = {};
testnet.type = 'testnet';
testnet.seeds = [
'hs-testnet.bcoin.ninja' // Christopher Jeffrey
];
testnet.magic = genesis.testnet.magic;
testnet.port = 13038;
testnet.brontidePort = 45806;
testnet.checkpointMap = {};
testnet.lastCheckpoint = 0;
testnet.halvingInterval = 170000;
testnet.coinbaseMaturity = 100;
testnet.genesis = genesis.testnet;
testnet.genesisBlock = genesis.testnetData;
testnet.pow = {};
// Probably minable very quick with 1 GPU.
testnet.pow.limit = new BN(
'00000000ffff0000000000000000000000000000000000000000000000000000',
'hex'
);
testnet.pow.bits = 0x1d00ffff;
testnet.pow.chainwork = new BN(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
testnet.pow.targetWindow = 144;
testnet.pow.targetSpacing = 10 * 60;
testnet.pow.blocksPerDay = ((24 * 60 * 60) / testnet.pow.targetSpacing) >>> 0;
testnet.pow.targetTimespan =
testnet.pow.targetWindow * testnet.pow.targetSpacing;
testnet.pow.minActual = (testnet.pow.targetTimespan / 4) >>> 0;
testnet.pow.maxActual = testnet.pow.targetTimespan * 4;
testnet.pow.targetReset = true;
testnet.pow.noRetargeting = false;
testnet.txStart = 0;
testnet.names = {
auctionStart: (0.25 * testnet.pow.blocksPerDay) | 0,
rolloutInterval: (0.25 * testnet.pow.blocksPerDay) | 0,
lockupPeriod: (0.25 * testnet.pow.blocksPerDay) | 0,
renewalWindow: 30 * testnet.pow.blocksPerDay,
renewalPeriod: 7 * testnet.pow.blocksPerDay,
renewalMaturity: 1 * testnet.pow.blocksPerDay,
claimPeriod: 90 * testnet.pow.blocksPerDay,
claimFrequency: 2 * testnet.pow.blocksPerDay,
biddingPeriod: 1 * testnet.pow.blocksPerDay,
revealPeriod: 2 * testnet.pow.blocksPerDay,
treeInterval: testnet.pow.blocksPerDay >>> 2,
transferLockup: 2 * testnet.pow.blocksPerDay,
revocationDelay: 4 * testnet.pow.blocksPerDay,
auctionMaturity: (1 + 2 + 4) * testnet.pow.blocksPerDay,
noRollout: false,
noReserved: false
};
testnet.block = {
pruneAfterHeight: 1000,
keepBlocks: 10000,
maxTipAge: 12 * 60 * 60,
slowHeight: 0
};
testnet.goosigStop = 20 * testnet.pow.blocksPerDay;
testnet.activationThreshold = 1512;
testnet.minerWindow = 2016;
testnet.deployments = {
hardening: {
name: 'hardening',
bit: 0,
startTime: 1581638400, // February 14th, 2020
timeout: 1707868800, // February 14th, 2024
threshold: -1,
window: -1,
required: false,
force: false
},
testdummy: {
name: 'testdummy',
bit: 28,
startTime: 1199145601, // January 1, 2008
timeout: 1230767999, // December 31, 2008
threshold: -1,
window: -1,
required: false,
force: true
}
};
testnet.deploys = [
testnet.deployments.hardening,
testnet.deployments.testdummy
];
testnet.keyPrefix = {
privkey: 0xef,
xpubkey: 0x043587cf,
xprivkey: 0x04358394,
xpubkey58: 'tpub',
xprivkey58: 'tprv',
coinType: 5354
};
testnet.addressPrefix = 'ts';
testnet.requireStandard = false;
testnet.rpcPort = 13037;
testnet.walletPort = 13039;
testnet.nsPort = 15349;
testnet.rsPort = 15350;
testnet.minRelay = 1000;
testnet.feeRate = 20000;
testnet.maxFeeRate = 60000;
testnet.identityKey = null;
testnet.selfConnect = false;
testnet.requestMempool = false;
testnet.claimPrefix = 'hns-testnet:';
testnet.deflationHeight = 0;
/*
* Regtest
*/
const regtest = {};
regtest.type = 'regtest';
regtest.seeds = [];
regtest.magic = genesis.regtest.magic;
regtest.port = 14038;
regtest.brontidePort = 46806;
regtest.checkpointMap = {};
regtest.lastCheckpoint = 0;
regtest.halvingInterval = 2500;
regtest.coinbaseMaturity = 2;
regtest.genesis = genesis.regtest;
regtest.genesisBlock = genesis.regtestData;
regtest.pow = {};
regtest.pow.limit = new BN(
'7fffff0000000000000000000000000000000000000000000000000000000000',
'hex'
);
regtest.pow.bits = 0x207fffff;
regtest.pow.chainwork = new BN(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
regtest.pow.targetWindow = 144;
regtest.pow.targetSpacing = 10 * 60;
regtest.pow.blocksPerDay = ((24 * 60 * 60) / regtest.pow.targetSpacing) >>> 0;
regtest.pow.targetTimespan =
regtest.pow.targetWindow * regtest.pow.targetSpacing;
regtest.pow.minActual = (regtest.pow.targetTimespan / 4) >>> 0;
regtest.pow.maxActual = regtest.pow.targetTimespan * 4;
regtest.pow.targetReset = true;
regtest.pow.noRetargeting = true;
regtest.txStart = 0;
regtest.names = {
auctionStart: 0,
rolloutInterval: 2,
lockupPeriod: 2,
renewalWindow: 5000,
renewalPeriod: 2500,
renewalMaturity: 50,
claimPeriod: 250000,
claimFrequency: 0,
biddingPeriod: 5,
revealPeriod: 10,
treeInterval: 5,
transferLockup: 10,
revocationDelay: 50,
auctionMaturity: 5 + 10 + 50,
noRollout: false,
noReserved: false
};
regtest.block = {
pruneAfterHeight: 1000,
keepBlocks: 10000,
maxTipAge: 0xffffffff,
slowHeight: 0
};
regtest.goosigStop = -1 >>> 0;
regtest.activationThreshold = 108;
regtest.minerWindow = 144;
regtest.deployments = {
hardening: {
name: 'hardening',
bit: 0,
startTime: 1581638400, // February 14th, 2020
timeout: 1707868800, // February 14th, 2024
threshold: -1,
window: -1,
required: false,
force: false
},
testdummy: {
name: 'testdummy',
bit: 28,
startTime: 0,
timeout: 0xffffffff,
threshold: -1,
window: -1,
required: false,
force: true
}
};
regtest.deploys = [
regtest.deployments.hardening,
regtest.deployments.testdummy
];
regtest.keyPrefix = {
privkey: 0x5a,
xpubkey: 0xeab4fa05,
xprivkey: 0xeab404c7,
xpubkey58: 'rpub',
xprivkey58: 'rprv',
coinType: 5355
};
regtest.addressPrefix = 'rs';
regtest.requireStandard = false;
regtest.rpcPort = 14037;
regtest.walletPort = 14039;
regtest.nsPort = 25349;
regtest.rsPort = 25350;
regtest.minRelay = 1000;
regtest.feeRate = 20000;
regtest.maxFeeRate = 60000;
regtest.identityKey = Buffer.from(
'104932181cfed7584105c728cdc0eb9af1e7ffdc4a00743fd45e5de66cac7668',
'hex'
);
regtest.selfConnect = true;
regtest.requestMempool = true;
regtest.claimPrefix = 'hns-regtest:';
regtest.deflationHeight = 200;
/*
* Simnet
*/
const simnet = {};
simnet.type = 'simnet';
simnet.seeds = [];
simnet.magic = genesis.simnet.magic;
simnet.port = 15038;
simnet.brontidePort = 47806;
simnet.checkpointMap = {};
simnet.lastCheckpoint = 0;
simnet.halvingInterval = 170000;
simnet.coinbaseMaturity = 6;
simnet.genesis = genesis.simnet;
simnet.genesisBlock = genesis.simnetData;
simnet.pow = {};
simnet.pow.limit = new BN(
'7fffff0000000000000000000000000000000000000000000000000000000000',
'hex'
);
simnet.pow.bits = 0x207fffff;
simnet.pow.chainwork = new BN(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
simnet.pow.targetWindow = 144;
simnet.pow.targetSpacing = 10 * 60;
simnet.pow.blocksPerDay = ((24 * 60 * 60) / simnet.pow.targetSpacing) >>> 0;
simnet.pow.targetTimespan =
simnet.pow.targetWindow * simnet.pow.targetSpacing;
simnet.pow.minActual = (simnet.pow.targetTimespan / 4) >>> 0;
simnet.pow.maxActual = simnet.pow.targetTimespan * 4;
simnet.pow.targetReset = false;
simnet.pow.noRetargeting = false;
simnet.txStart = 0;
simnet.names = {
auctionStart: 0,
rolloutInterval: 1,
lockupPeriod: 1,
renewalWindow: 2500,
renewalPeriod: 1250,
renewalMaturity: 25,
claimPeriod: 75000,
claimFrequency: 0,
biddingPeriod: 25,
revealPeriod: 50,
treeInterval: 2,
transferLockup: 5,
revocationDelay: 25,
auctionMaturity: 25 + 50 + 25,
noRollout: false,
noReserved: false
};
simnet.block = {
pruneAfterHeight: 1000,
keepBlocks: 10000,
maxTipAge: 0xffffffff,
slowHeight: 0
};
simnet.goosigStop = -1 >>> 0;
simnet.activationThreshold = 75;
simnet.minerWindow = 100;
simnet.deployments = {
hardening: {
name: 'hardening',
bit: 0,
startTime: 1581638400, // February 14th, 2020
timeout: 1707868800, // February 14th, 2024
threshold: -1,
window: -1,
required: false,
force: false
},
testdummy: {
name: 'testdummy',
bit: 28,
startTime: 1199145601, // January 1, 2008
timeout: 1230767999, // December 31, 2008
threshold: -1,
window: -1,
required: false,
force: true
}
};
simnet.deploys = [
simnet.deployments.hardening,
simnet.deployments.testdummy
];
simnet.keyPrefix = {
privkey: 0x64,
xpubkey: 0x0420bd3a,
xprivkey: 0x0420b900,
xpubkey58: 'spub',
xprivkey58: 'sprv',
coinType: 5356
};
simnet.addressPrefix = 'ss';
simnet.requireStandard = false;
simnet.rpcPort = 15037;
simnet.walletPort = 15039;
simnet.nsPort = 35349;
simnet.rsPort = 35350;
simnet.minRelay = 1000;
simnet.feeRate = 20000;
simnet.maxFeeRate = 60000;
simnet.identityKey = Buffer.from(
'104932181cfed7584105c728cdc0eb9af1e7ffdc4a00743fd45e5de66cac7668',
'hex'
);
simnet.selfConnect = true;
simnet.requestMempool = false;
simnet.claimPrefix = 'hns-simnet:';
simnet.deflationHeight = 0;
/*
* Expose
*/
network.main = main;
network.testnet = testnet;
network.regtest = regtest;
network.simnet = simnet;
}],
[/* 47 */ 'hsd', '/lib/protocol/genesis.js', function(exports, module, __filename, __dirname, __meta) {
// Autogenerated, do not edit.
'use strict';
const data = __node_require__(48 /* './genesis-data.json' */);
const genesis = exports;
/*
* Main
*/
genesis.main = {
version: 0,
hash: Buffer.from(
'5b6ef2d3c1f3cdcadfd9a030ba1811efdd17740f14e166489760741d075992e0',
'hex'),
prevBlock: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
merkleRoot: Buffer.from(
'8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15',
'hex'),
witnessRoot: Buffer.from(
'1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351',
'hex'),
treeRoot: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
reservedRoot: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
time: 1580745078,
bits: 0x1c00ffff,
nonce: 0x00000000,
extraNonce: Buffer.from(
'000000000000000000000000000000000000000000000000',
'hex'),
mask: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
height: 0,
magic: 1533997779
};
genesis.mainData = Buffer.from(data.main, 'base64');
/*
* Testnet
*/
genesis.testnet = {
version: 0,
hash: Buffer.from(
'b1520dd24372f82ec94ebf8cf9d9b037d419c4aa3575d05dec70aedd1b427901',
'hex'),
prevBlock: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
merkleRoot: Buffer.from(
'8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15',
'hex'),
witnessRoot: Buffer.from(
'1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351',
'hex'),
treeRoot: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
reservedRoot: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
time: 1580745079,
bits: 0x1d00ffff,
nonce: 0x00000000,
extraNonce: Buffer.from(
'000000000000000000000000000000000000000000000000',
'hex'),
mask: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
height: 0,
magic: 2974944722
};
genesis.testnetData = Buffer.from(data.testnet, 'base64');
/*
* Regtest
*/
genesis.regtest = {
version: 0,
hash: Buffer.from(
'ae3895cf597eff05b19e02a70ceeeecb9dc72dbfe6504a50e9343a72f06a87c5',
'hex'),
prevBlock: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
merkleRoot: Buffer.from(
'8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15',
'hex'),
witnessRoot: Buffer.from(
'1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351',
'hex'),
treeRoot: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
reservedRoot: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
time: 1580745080,
bits: 0x207fffff,
nonce: 0x00000000,
extraNonce: Buffer.from(
'000000000000000000000000000000000000000000000000',
'hex'),
mask: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
height: 0,
magic: 2922943951
};
genesis.regtestData = Buffer.from(data.regtest, 'base64');
/*
* Simnet
*/
genesis.simnet = {
version: 0,
hash: Buffer.from(
'0e648edc9cddb179014658061ea3f666a45cf44881877ae506e6babefbef6992',
'hex'),
prevBlock: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
merkleRoot: Buffer.from(
'8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15',
'hex'),
witnessRoot: Buffer.from(
'1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351',
'hex'),
treeRoot: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
reservedRoot: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
time: 1580745081,
bits: 0x207fffff,
nonce: 0x00000000,
extraNonce: Buffer.from(
'000000000000000000000000000000000000000000000000',
'hex'),
mask: Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'),
height: 0,
magic: 241471196
};
genesis.simnetData = Buffer.from(data.simnet, 'base64');
}],
[/* 48 */ 'hsd', '/lib/protocol/genesis-data.json', function(exports, module, __filename, __dirname, __meta) {
module.exports = {
"main": "AAAAAHZBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//wAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8=",
"testnet": "AAAAAHdBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//wAdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8=",
"regtest": "AAAAAHhBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//38gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8=",
"simnet": "AAAAAHlBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//38gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8="
};
}],
[/* 49 */ 'hsd', '/lib/protocol/timedata.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* timedata.js - time management for hsd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
'use strict';
const EventEmitter = require('events');
const util = __node_require__(50 /* '../utils/util' */);
const binary = __node_require__(45 /* '../utils/binary' */);
/**
* Time Data
* An object which handles "adjusted time". This may not
* look it, but this is actually a semi-consensus-critical
* piece of code. It handles version packets from peers
* and calculates what to offset our system clock's time by.
* @alias module:protocol.TimeData
* @extends EventEmitter
* @property {Array} samples
* @property {Object} known
* @property {Number} limit
* @property {Number} offset
*/
class TimeData extends EventEmitter {
/**
* Create time data.
* @constructor
* @param {Number} [limit=200]
*/
constructor(limit) {
super();
if (limit == null)
limit = 200;
this.samples = [];
this.known = new Map();
this.limit = limit;
this.offset = 0;
this.checked = false;
}
/**
* Add time data.
* @param {String} id
* @param {Number} time
*/
add(id, time) {
if (this.samples.length >= this.limit)
return;
if (this.known.has(id))
return;
const sample = time - util.now();
this.known.set(id, sample);
binary.insert(this.samples, sample, compare);
this.emit('sample', sample, this.samples.length);
if (this.samples.length >= 5 && this.samples.length % 2 === 1) {
let median = this.samples[this.samples.length >>> 1];
if (Math.abs(median) >= 70 * 60) {
if (!this.checked) {
let match = false;
for (const offset of this.samples) {
if (offset !== 0 && Math.abs(offset) < 5 * 60) {
match = true;
break;
}
}
if (!match) {
this.checked = true;
this.emit('mismatch');
}
}
median = 0;
}
this.offset = median;
this.emit('offset', this.offset);
}
}
/**
* Get the current adjusted time.
* @returns {Number} Adjusted Time.
*/
now() {
return util.now() + this.offset;
}
/**
* Adjust a timestamp.
* @param {Number} time
* @returns {Number} Adjusted Time.
*/
adjust(time) {
return time + this.offset;
}
/**
* Unadjust a timestamp.
* @param {Number} time
* @returns {Number} Local Time.
*/
local(time) {
return time - this.offset;
}
/**
* Get the current adjusted time in milliseconds.
* @returns {Number} Adjusted Time.
*/
ms() {
return Date.now() + this.offset * 1000;
}
}
/*
* Helpers
*/
function compare(a, b) {
return a - b;
}
/*
* Expose
*/
module.exports = TimeData;
}],
[/* 50 */ 'hsd', '/lib/utils/util.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* util.js - utils for hsd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
'use strict';
const assert = __node_require__(2 /* 'bsert' */);
/**
* @exports utils/util
*/
const util = exports;
/**
* Return hrtime (shim for browser).
* @param {Array} time
* @returns {Array} [seconds, nanoseconds]
*/
util.bench = function bench(time) {
if (!process.hrtime) {
const now = Date.now();
if (time) {
const [hi, lo] = time;
const start = hi * 1000 + lo / 1e6;
return now - start;
}
const ms = now % 1000;
// Seconds
const hi = (now - ms) / 1000;
// Nanoseconds
const lo = ms * 1e6;
return [hi, lo];
}
if (time) {
const [hi, lo] = process.hrtime(time);
return hi * 1000 + lo / 1e6;
}
return process.hrtime();
};
/**
* Get current time in unix time (seconds).
* @returns {Number}
*/
util.now = function now() {
return Math.floor(Date.now() / 1000);
};
/**
* Get current time in unix time (milliseconds).
* @returns {Number}
*/
util.ms = function ms() {
return Date.now();
};
/**
* Create a Date ISO string from time in unix time (seconds).
* @param {Number?} time - Seconds in unix time.
* @returns {String}
*/
util.date = function date(time) {
if (time == null)
time = util.now();
return new Date(time * 1000).toISOString().slice(0, -5) + 'Z';
};
/**
* Get unix seconds from a Date string.
* @param {String?} date - Date ISO String.
* @returns {Number}
*/
util.time = function time(date) {
if (date == null)
return util.now();
return new Date(date) / 1000 | 0;
};
/**
* Convert u32 to padded hex.
* @param {Number} num
* @returns {String}
*/
util.hex32 = function hex32(num) {
assert((num >>> 0) === num);
num = num.toString(16);
switch (num.length) {
case 1:
return `0000000${num}`;
case 2:
return `000000${num}`;
case 3:
return `00000${num}`;
case 4:
return `0000${num}`;
case 5:
return `000${num}`;
case 6:
return `00${num}`;
case 7:
return `0${num}`;
case 8:
return `${num}`;
default:
throw new Error();
}
};
/**
* Parse hex.
* @param {String} str
* @param {Number} size
* @returns {Buffer}
*/
util.parseHex = function parseHex(str, size) {
if (size == null)
size = -1;
assert(typeof str === 'string');
assert(size === -1 || (size >>> 0) === size);
if (str.length & 1)
throw new Error('Invalid hex string.');
if (size !== -1) {
if ((str.length >>> 1) !== size)
throw new Error('Invalid hex string.');
}
const data = Buffer.from(str, 'hex');
if (data.length !== (str.length >>> 1))
throw new Error('Invalid hex string.');
return data;
};
/**
* Test whether a number is a safe uint64.
* @param {Number} num
* @returns {Boolean}
*/
util.isU64 = function isU64(num) {
return Number.isSafeInteger(num) && num >= 0;
};
/**
* Encode a uint32.
* @param {Number} num
* @returns {Buffer}
*/
util.encodeU32 = function encodeU32(num) {
assert(Number.isSafeInteger(num));
const buf = Buffer.allocUnsafe(4);
buf[0] = num;
num >>>= 8;
buf[1] = num;
num >>>= 8;
buf[2] = num;
num >>>= 8;
buf[3] = num;
return buf;
};
}],
[/* 51 */ 'hsd', '/lib/protocol/consensus.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* consensus.js - consensus constants and helpers for hsd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
'use strict';
/**
* @module protocol/consensus
*/
const assert = __node_require__(2 /* 'bsert' */);
const BN = __node_require__(31 /* 'bcrypto/lib/bn.js' */);
/**
* Coin exponent.
* @const {Number}
* @default
*/
exports.EXP = 6;
/**
* One handshake in dollarydoos.
* @const {Amount}
* @default
*/
exports.COIN = Math.pow(10, exports.EXP);
/**
* Maximum creators amount in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_CREATORS = 102e6 * exports.COIN;
/**
* Maximum sponsors amount in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_SPONSORS = 102e6 * exports.COIN;
/**
* Maximum TLD holder amount in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_TLD = 51e6 * exports.COIN;
/**
* Maximum domain holder amount in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_DOMAIN = 51e6 * exports.COIN;
/**
* Maximum CA/naming amount in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_CA_NAMING = 102e6 * exports.COIN;
/**
* Maximum airdrop amount in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_AIRDROP = 0.952e9 * exports.COIN;
/**
* Maximum initial supply in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_INITIAL = 1.36e9 * exports.COIN;
assert(exports.MAX_CREATORS
+ exports.MAX_SPONSORS
+ exports.MAX_TLD
+ exports.MAX_DOMAIN
+ exports.MAX_CA_NAMING
+ exports.MAX_AIRDROP === exports.MAX_INITIAL);
/**
* Maximum amount of subsidies in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_SUBSIDY = 0.68e9 * exports.COIN;
assert(exports.MAX_INITIAL / 2 === exports.MAX_SUBSIDY);
/**
* Maximum amount of money in dollarydoos (consensus).
* @const {Amount}
* @default
*/
exports.MAX_MONEY = 2.04e9 * exports.COIN;
assert(exports.MAX_INITIAL + exports.MAX_SUBSIDY === exports.MAX_MONEY);
/**
* Base block subsidy (consensus).
* @const {Amount}
* @default
*/
exports.BASE_REWARD = 2000 * exports.COIN;
assert(2 * exports.BASE_REWARD * 170000 === exports.MAX_SUBSIDY);
/**
* Block subsidy specifically for the genesis block.
*
* Explanation:
* The max miner subsidy is 680000000, but due
* to the halving interval it actually ends up
* as 679999995.79, so add 2.21 coins to the
* genesis reward output to make MAX_MONEY a
* thoroughly true value.
*
* This, combined with the 3 1/4 year halving
* interval, causes the supply to run dry
* after about 100 years (around the year 2119,
* or height=5,270,000).
*
* @const {Amount}
* @default
*/
exports.GENESIS_REWARD = exports.BASE_REWARD + ((2.21 * exports.COIN) | 0);
/**
* Genesis key.
* @const {Buffer}
*/
exports.GENESIS_KEY =
Buffer.from('f0237ae2e8f860f7d79124fc513f012e5aaa8d23', 'hex');
/**
* Maximum block base size (consensus).
* @const {Number}
* @default
*/
exports.MAX_BLOCK_SIZE = 1000000;
/**
* Maximum block serialization size (protocol).
* @const {Number}
* @default
*/
exports.MAX_RAW_BLOCK_SIZE = 4000000;
/**
* Maximum block weight (consensus).
* @const {Number}
* @default
*/
exports.MAX_BLOCK_WEIGHT = 4000000;
/**
* Maximum block sigops cost (consensus).
* @const {Number}
* @default
*/
exports.MAX_BLOCK_SIGOPS = 80000;
/**
* Maximum block tree opens.
* @const {Number}
* @default
*/
exports.MAX_BLOCK_OPENS = 300;
/**
* Maximum block tree updates.
* @const {Number}
* @default
*/
exports.MAX_BLOCK_UPDATES = 600;
/**
* Maximum block tree renewals.
* @const {Number}
* @default
*/
exports.MAX_BLOCK_RENEWALS = 600;
/**
* Size of set to pick median time from.
* @const {Number}
* @default
*/
exports.MEDIAN_TIMESPAN = 11;
/**
* Amount to multiply base/non-witness sizes by.
* @const {Number}
* @default
*/
exports.WITNESS_SCALE_FACTOR = 4;
/**
* Maximum TX base size (consensus).
* @const {Number}
* @default
*/
exports.MAX_TX_SIZE = 1000000;
/**
* Maximum TX weight (consensus).
* @const {Number}
* @default
*/
exports.MAX_TX_WEIGHT = 4000000;
/**
* Locktime flag.
* @const {Number}
* @default
*/
exports.LOCKTIME_FLAG = (1 << 31) >>> 0;
/**
* Locktime mask.
* @const {Number}
* @default
*/
exports.LOCKTIME_MASK = exports.LOCKTIME_FLAG - 1;
/**
* Locktime granularity.
* @const {Number}
* @default
*/
exports.LOCKTIME_GRANULARITY = 9;
/**
* Locktime multiplier.
* @const {Number}
* @default
*/
exports.LOCKTIME_MULT = 2 ** exports.LOCKTIME_GRANULARITY;
/**
* Highest nSequence bit -- disables
* sequence locktimes (consensus).
* @const {Number}
*/
exports.SEQUENCE_DISABLE_FLAG = (1 << 31) >>> 0;
/**
* Sequence time: height or time (consensus).
* @const {Number}
* @default
*/
exports.SEQUENCE_TYPE_FLAG = 1 << 22;
/**
* Sequence granularity for time (consensus).
* @const {Number}
* @default
*/
exports.SEQUENCE_GRANULARITY = 9;
/**
* Sequence mask (consensus).
* @const {Number}
* @default
*/
exports.SEQUENCE_MASK = 0x0000ffff;
/**
* Max serialized script size (consensus).
* @const {Number}
* @default
*/
exports.MAX_SCRIPT_SIZE = 10000;
/**
* Max stack size during execution (consensus).
* @const {Number}
* @default
*/
exports.MAX_SCRIPT_STACK = 1000;
/**
* Max script element size (consensus).
* @const {Number}
* @default
*/
exports.MAX_SCRIPT_PUSH = 520;
/**
* Max opcodes executed (consensus).
* @const {Number}
* @default
*/
exports.MAX_SCRIPT_OPS = 201;
/**
* Max `n` value for multisig (consensus).
* @const {Number}
* @default
*/
exports.MAX_MULTISIG_PUBKEYS = 20;
/**
* A hash of all zeroes.
* @const {Buffer}
* @default
*/
exports.ZERO_HASH = Buffer.alloc(32, 0x00);
/**
* Block header size.
* @const {Number}
* @default
*/
exports.HEADER_SIZE = 236;
/**
* Block header nonce size.
* @const {Number}
* @default
*/
exports.NONCE_SIZE = 24;
/**
* Block header of all zeroes.
* @const {Buffer}
* @default
*/
exports.ZERO_HEADER = Buffer.alloc(exports.HEADER_SIZE, 0x00);
/**
* Block header nonce of all zeroes.
* @const {Buffer}
* @default
*/
exports.ZERO_NONCE = Buffer.alloc(exports.NONCE_SIZE, 0x00);
/**
* Convert a compact number to a big number.
* Used for `block.bits` -> `target` conversion.
* @param {Number} compact
* @returns {BN}
*/
exports.fromCompact = function fromCompact(compact) {
if (compact === 0)
return new BN(0);
const exponent = compact >>> 24;
const negative = (compact >>> 23) & 1;
let mantissa = compact & 0x7fffff;
let num;
if (exponent <= 3) {
mantissa >>>= 8 * (3 - exponent);
num = new BN(mantissa);
} else {
num = new BN(mantissa);
num.iushln(8 * (exponent - 3));
}
if (negative)
num.ineg();
return num;
};
/**
* Convert a big number to a compact number.
* Used for `target` -> `block.bits` conversion.
* @param {BN} num
* @returns {Number}
*/
exports.toCompact = function toCompact(num) {
if (num.isZero())
return 0;
let exponent = num.byteLength();
let mantissa;
if (exponent <= 3) {
mantissa = num.toNumber();
mantissa <<= 8 * (3 - exponent);
} else {
mantissa = num.ushrn(8 * (exponent - 3)).toNumber();
}
if (mantissa & 0x800000) {
mantissa >>>= 8;
exponent += 1;
}
let compact = (exponent << 24) | mantissa;
if (num.isNeg())
compact |= 0x800000;
compact >>>= 0;
return compact;
};
/**
* Verify proof-of-work.
* @param {Hash} hash
* @param {Number} bits
* @returns {Boolean}
*/
exports.verifyPOW = function verifyPOW(hash, bits) {
const target = exports.fromCompact(bits);
if (target.isNeg() || target.isZero())
return false;
if (target.bitLength() > 256)
return false;
const num = new BN(hash, 'be');
if (num.gt(target))
return false;
return true;
};
/**
* Calculate block subsidy.
* @param {Number} height - Reward era by height.
* @returns {Amount}
*/
exports.getReward = function getReward(height, interval) {
assert((height >>> 0) === height, 'Bad height for reward.');
assert((interval >>> 0) === interval);
const halvings = Math.floor(height / interval);
if (halvings >= 52)
return 0;
return Math.floor(exports.BASE_REWARD / Math.pow(2, halvings));
};
/**
* Test version bit.
* @param {Number} version
* @param {Number} bit
* @returns {Boolean}
*/
exports.hasBit = function hasBit(version, bit) {
return (version & (1 << bit)) !== 0;
};
}],
[/* 52 */ 'hsd', '/lib/hd/common.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* common.js - common functions for hd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
'use strict';
const assert = __node_require__(2 /* 'bsert' */);
const LRU = __node_require__(53 /* 'blru' */);
const common = exports;
/**
* Index at which hardening begins.
* @const {Number}
* @default
*/
common.HARDENED = 0x80000000;
/**
* Min entropy bits.
* @const {Number}
* @default
*/
common.MIN_ENTROPY = 128;
/**
* Max entropy bits.
* @const {Number}
* @default
*/
common.MAX_ENTROPY = 512;
/**
* LRU cache to avoid deriving keys twice.
* @type {LRU}
*/
common.cache = new LRU(500);
/**
* Parse a derivation path and return an array of indexes.
* @see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
* @param {String} path
* @param {Boolean} hard
* @returns {Number[]}
*/
common.parsePath = function parsePath(path, hard) {
assert(typeof path === 'string');
assert(typeof hard === 'boolean');
assert(path.length >= 1);
assert(path.length <= 3062);
const parts = path.split('/');
const root = parts[0];
if (root !== 'm'
&& root !== 'M'
&& root !== 'm\''
&& root !== 'M\'') {
throw new Error('Invalid path root.');
}
const result = [];
for (let i = 1; i < parts.length; i++) {
let part = parts[i];
const hardened = part[part.length - 1] === '\'';
if (hardened)
part = part.slice(0, -1);
if (part.length > 10)
throw new Error('Path index too large.');
if (!/^\d+$/.test(part))
throw new Error('Path index is non-numeric.');
let index = parseInt(part, 10);
if ((index >>> 0) !== index)
throw new Error('Path index out of range.');
if (hardened) {
index |= common.HARDENED;
index >>>= 0;
}
if (!hard && (index & common.HARDENED))
throw new Error('Path index cannot be hardened.');
result.push(index);
}
return result;
};
/**
* Test whether the key is a master key.
* @param {HDPrivateKey|HDPublicKey} key
* @returns {Boolean}
*/
common.isMaster = function isMaster(key) {
return key.depth === 0
&& key.childIndex === 0
&& key.parentFingerPrint === 0;
};
/**
* Test whether the key is (most likely) a BIP44 account key.
* @param {HDPrivateKey|HDPublicKey} key
* @param {Number?} account
* @returns {Boolean}
*/
common.isAccount = function isAccount(key, account) {
if (account != null) {
const index = (common.HARDENED | account) >>> 0;
if (key.childIndex !== index)
return false;
}
return key.depth === 3 && (key.childIndex & common.HARDENED) !== 0;
};
/**
* A compressed pubkey of all zeroes.
* @const {Buffer}
* @default
*/
common.ZERO_KEY = Buffer.alloc(33, 0x00);
}],
[/* 53 */ 'blru', '/lib/blru.js', function(exports, module, __filename, __dirname, __meta) {
'use strict';
module.exports = __node_require__(54 /* './lru' */);
}],
[/* 54 */ 'blru', '/lib/lru.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* lru.js - LRU cache for bcoin
* Copyright (c) 2014-2018, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = __node_require__(2 /* 'bsert' */);
/**
* LRU Cache
*/
class LRU {
/**
* Create an LRU cache.
* @constructor
* @param {Number} capacity
* @param {Function?} getSize
* @param {Function?} CustomMap
*/
constructor(capacity, getSize, CustomMap) {
assert(typeof capacity === 'number', 'Capacity must be a number.');
assert(capacity >= 0, 'Capacity cannot be negative.');
assert(!getSize || typeof getSize === 'function', 'Bad size callback.');
assert(!CustomMap || typeof CustomMap === 'function');
this.map = CustomMap ? new CustomMap() : new Map();
this.size = 0;
this.items = 0;
this.head = null;
this.tail = null;
this.pending = null;
this.capacity = capacity;
this.getSize = getSize;
}
/**
* Calculate size of an item.
* @private
* @param {LRUItem} item
* @returns {Number} Size.
*/
_getSize(item) {
if (this.getSize)
return 120 + this.getSize(item.value, item.key);
return 1;
}
/**
* Compact the LRU linked list.
* @private
*/
_compact() {
if (this.size <= this.capacity)
return;
let item = null;
let next = null;
for (item = this.head; item; item = next) {
if (this.size <= this.capacity)
break;
this.size -= this._getSize(item);
this.items -= 1;
this.map.delete(item.key);
next = item.next;
item.prev = null;
item.next = null;
}
if (!item) {
this.head = null;
this.tail = null;
return;
}
this.head = item;
item.prev = null;
}
/**
* Reset the cache. Clear all items.
*/
reset() {
let item, next;
for (item = this.head; item; item = next) {
this.map.delete(item.key);
this.items -= 1;
next = item.next;
item.prev = null;
item.next = null;
}
assert(!item);
this.size = 0;
this.head = null;
this.tail = null;
}
/**
* Add an item to the cache.
* @param {String|Number} key
* @param {Object} value
*/
set(key, value) {
if (this.capacity === 0)
return;
let item = this.map.get(key);
if (item) {
this.size -= this._getSize(item);
item.value = value;
this.size += this._getSize(item);
this._removeList(item);
this._appendList(item);
this._compact();
return;
}
item = new LRUItem(key, value);
this.map.set(key, item);
this._appendList(item);
this.size += this._getSize(item);
this.items += 1;
this._compact();
}
/**
* Retrieve an item from the cache.
* @param {String|Number} key
* @returns {Object} Item.
*/
get(key) {
if (this.capacity === 0)
return null;
const item = this.map.get(key);
if (!item)
return null;
this._removeList(item);
this._appendList(item);
return item.value;
}
/**
* Test whether the cache contains a key.
* @param {String|Number} key
* @returns {Boolean}
*/
has(key) {
if (this.capacity === 0)
return false;
return this.map.has(key);
}
/**
* Remove an item from the cache.
* @param {String|Number} key
* @returns {Boolean} Whether an item was removed.
*/
remove(key) {
if (this.capacity === 0)
return false;
const item = this.map.get(key);
if (!item)
return false;
this.size -= this._getSize(item);
this.items -= 1;
this.map.delete(key);
this._removeList(item);
return true;
}
/**
* Prepend an item to the linked list (sets new head).
* @private
* @param {LRUItem}
*/
_prependList(item) {
this._insertList(null, item);
}
/**
* Append an item to the linked list (sets new tail).
* @private
* @param {LRUItem}
*/
_appendList(item) {
this._insertList(this.tail, item);
}
/**
* Insert item into the linked list.
* @private
* @param {LRUItem|null} ref
* @param {LRUItem} item
*/
_insertList(ref, item) {
assert(!item.next);
assert(!item.prev);
if (ref == null) {
if (!this.head) {
this.head = item;
this.tail = item;
} else {
this.head.prev = item;
item.next = this.head;
this.head = item;
}
return;
}
item.next = ref.next;
item.prev = ref;
ref.next = item;
if (item.next)
item.next.prev = item;
if (ref === this.tail)
this.tail = item;
}
/**
* Remove item from the linked list.
* @private
* @param {LRUItem}
*/
_removeList(item) {
if (item.prev)
item.prev.next = item.next;
if (item.next)
item.next.prev = item.prev;
if (item === this.head)
this.head = item.next;
if (item === this.tail)
this.tail = item.prev || this.head;
if (!this.head)
assert(!this.tail);
if (!this.tail)
assert(!this.head);
item.prev = null;
item.next = null;
}
/**
* Collect all keys in the cache, sorted by LRU.
* @returns {String[]}
*/
keys() {
const items = [];
for (let item = this.head; item; item = item.next) {
if (item === this.head)
assert(!item.prev);
if (!item.prev)
assert(item === this.head);
if (!item.next)
assert(item === this.tail);
items.push(item.key);
}
return items;
}
/**
* Collect all values in the cache, sorted by LRU.
* @returns {String[]}
*/
values() {
const items = [];
for (let item = this.head; item; item = item.next)
items.push(item.value);
return items;
}
/**
* Convert the LRU cache to an array of items.
* @returns {Object[]}
*/
toArray() {
const items = [];
for (let item = this.head; item; item = item.next)
items.push(item);
return items;
}
/**
* Create an atomic batch for the lru
* (used for caching database writes).
* @returns {LRUBatch}
*/
batch() {
return new LRUBatch(this);
}
/**
* Start the pending batch.
*/
start() {
assert(!this.pending);
this.pending = this.batch();
}
/**
* Clear the pending batch.
*/
clear() {
assert(this.pending);
this.pending.clear();
}
/**
* Drop the pending batch.
*/
drop() {
assert(this.pending);
this.pending = null;
}
/**
* Commit the pending batch.
*/
commit() {
assert(this.pending);
this.pending.commit();
this.pending = null;
}
/**
* Push an item onto the pending batch.
* @param {String} key
* @param {Object} value
*/
push(key, value) {
assert(this.pending);
if (this.capacity === 0)
return;
this.pending.set(key, value);
}
/**
* Push a removal onto the pending batch.
* @param {String} key
*/
unpush(key) {
assert(this.pending);
if (this.capacity === 0)
return;
this.pending.remove(key);
}
}
/**
* LRU Item
* @alias module:utils.LRUItem
*/
class LRUItem {
/**
* Create an LRU item.
* @constructor
* @private
* @param {String} key
* @param {Object} value
*/
constructor(key, value) {
this.key = key;
this.value = value;
this.next = null;
this.prev = null;
}
}
/**
* LRU Batch
* @alias module:utils.LRUBatch
*/
class LRUBatch {
/**
* Create an LRU batch.
* @constructor
* @param {LRU} lru
*/
constructor(lru) {
this.lru = lru;
this.ops = [];
}
/**
* Push an item onto the batch.
* @param {String} key
* @param {Object} value
*/
set(key, value) {
this.ops.push(new LRUOp(false, key, value));
}
/**
* Push a removal onto the batch.
* @param {String} key
*/
remove(key) {
this.ops.push(new LRUOp(true, key, null));
}
/**
* Clear the batch.
*/
clear() {
this.ops.length = 0;
}
/**
* Commit the batch.
*/
commit() {
for (const op of this.ops) {
if (op.remove) {
this.lru.remove(op.key);
continue;
}
this.lru.set(op.key, op.value);
}
this.ops.length = 0;
}
}
/**
* LRU Op
* @alias module:utils.LRUOp
* @private
*/
class LRUOp {
/**
* Create an LRU op.
* @constructor
* @param {Boolean} remove
* @param {String} key
* @param {Object} value
*/
constructor(remove, key, value) {
this.remove = remove;
this.key = key;
this.value = value;
}
}
/*
* Expose
*/
module.exports = LRU;
}],
[/* 55 */ 'hsd', '/lib/primitives/address.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* address.js - address object for hsd
* Copyright (c) 2017-2018, Christopher Jeffrey (MIT License).
* https://github.com/handshake-org/hsd
*/
'use strict';
const assert = __node_require__(2 /* 'bsert' */);
const bio = __node_require__(3 /* 'bufio' */);
const bech32 = __node_require__(56 /* 'bcrypto/lib/encoding/bech32' */);
const blake2b = __node_require__(58 /* 'bcrypto/lib/blake2b' */);
const sha3 = __node_require__(60 /* 'bcrypto/lib/sha3' */);
const Network = __node_require__(44 /* '../protocol/network' */);
const consensus = __node_require__(51 /* '../protocol/consensus' */);
/*
* Constants
*/
const ZERO_HASH160 = Buffer.alloc(20, 0x00);
/**
* Address
* Represents an address.
* @alias module:primitives.Address
* @property {Number} version
* @property {Buffer} hash
*/
class Address extends bio.Struct {
/**
* Create an address.
* @constructor
* @param {Object?} options
*/
constructor(options, network) {
super();
this.version = 0;
this.hash = ZERO_HASH160;
if (options)
this.fromOptions(options, network);
}
/**
* Inject properties from options object.
* @private
* @param {Object} options
*/
fromOptions(options, network) {
if (typeof options === 'string')
return this.fromString(options, network);
assert(options);
const {hash, version} = options;
return this.fromHash(hash, version);
}
/**
* Count the sigops in a script, taking into account witness programs.
* @param {Witness} witness
* @returns {Number} sigop count
*/
getSigops(witness) {
if (this.version === 0) {
if (this.hash.length === 20)
return 1;
if (this.hash.length === 32 && witness.items.length > 0) {
const redeem = witness.getRedeem();
return redeem.getSigops();
}
}
return 0;
}
/**
* Get the address hash.
* @returns {Hash}
*/
getHash() {
return this.hash;
}
/**
* Test whether the address is null.
* @returns {Boolean}
*/
isNull() {
if (this.hash.length === 20)
return this.hash.equals(ZERO_HASH160);
if (this.hash.length === 32)
return this.hash.equals(consensus.ZERO_HASH);
for (let i = 0; i < this.hash.length; i++) {
if (this.hash[i] !== 0)
return false;
}
return true;
}
/**
* Test whether the address is unspendable.
* @returns {Boolean}
*/
isUnspendable() {
return this.isNulldata();
}
/**
* Test equality against another address.
* @param {Address} addr
* @returns {Boolean}
*/
equals(addr) {
assert(addr instanceof Address);
return this.version === addr.version
&& this.hash.equals(addr.hash);
}
/**
* Compare against another address.
* @param {Address} addr
* @returns {Boolean}
*/
compare(addr) {
assert(addr instanceof Address);
const cmp = this.version - addr.version;
if (cmp !== 0)
return cmp;
return this.hash.compare(addr.hash);
}
/**
* Inject properties from another address.
* @param {Address} addr
* @returns {Boolean}
*/
inject(addr) {
this.version = addr.version;
this.hash = addr.hash;
return this;
}
/**
* Clone address.
* @returns {Address}
*/
clone() {
return new this.constructor().inject(this);
}
/**
* Compile the address object to a bech32 address.
* @param {{NetworkType|Network)?} network
* @returns {String}
* @throws Error on bad hash/prefix.
*/
toString(network) {
const version = this.version;
const hash = this.hash;
assert(version <= 31);
assert(hash.length >= 2 && hash.length <= 40);
network = Network.get(network);
const hrp = network.addressPrefix;
return bech32.encode(hrp, version, hash);
}
/**
* Instantiate address from pubkey.
* @param {Buffer} key
* @returns {Address}
*/
fromPubkey(key) {
assert(Buffer.isBuffer(key) && key.length === 33);
return this.fromHash(blake2b.digest(key, 20), 0);
}
/**
* Instantiate address from script.
* @param {Script} script
* @returns {Address}
*/
fromScript(script) {
assert(script && typeof script.encode === 'function');
return this.fromHash(sha3.digest(script.encode()), 0);
}
/**
* Inject properties from bech32 address.
* @private
* @param {String} data
* @param {Network?} network
* @throws Parse error
*/
fromString(data, network) {
assert(typeof data === 'string');
const [hrp, version, hash] = bech32.decode(data);
Network.fromAddress(hrp, network);
return this.fromHash(hash, version);
}
/**
* Inject properties from witness.
* @private
* @param {Witness} witness
*/
fromWitness(witness) {
const [, pk] = witness.getPubkeyhashInput();
if (pk) {
this.hash = blake2b.digest(pk, 20);
this.version = 0;
return this;
}
const redeem = witness.getScripthashInput();
if (redeem) {
this.hash = sha3.digest(redeem);
this.version = 0;
return this;
}
return null;
}
/**
* Inject properties from a hash.
* @private
* @param {Buffer|Hash} hash
* @param {Number} [version=-1]
* @throws on bad hash size
*/
fromHash(hash, version) {
if (version == null)
version = 0;
assert(Buffer.isBuffer(hash));
assert((version & 0xff) === version);
assert(version >= 0 && version <= 31, 'Bad program version.');
assert(hash.length >= 2 && hash.length <= 40, 'Hash is the wrong size.');
if (version === 0) {
assert(hash.length === 20 || hash.length === 32,
'Witness program hash is the wrong size.');
}
this.hash = hash;
this.version = version;
return this;
}
/**
* Inject properties from witness pubkeyhash.
* @private
* @param {Buffer} hash
* @returns {Address}
*/
fromPubkeyhash(hash) {
assert(hash && hash.length === 20, 'P2WPKH must be 20 bytes.');
return this.fromHash(hash, 0);
}
/**
* Inject properties from witness scripthash.
* @private
* @param {Buffer} hash
* @returns {Address}
*/
fromScripthash(hash) {
assert(hash && hash.length === 32, 'P2WSH must be 32 bytes.');
return this.fromHash(hash, 0);
}
/**
* Inject properties from witness program.
* @private
* @param {Number} version
* @param {Buffer} hash
* @returns {Address}
*/
fromProgram(version, hash) {
assert(version >= 0, 'Bad version for witness program.');
return this.fromHash(hash, version);
}
/**
* Instantiate address from nulldata.
* @param {Buffer} data
* @returns {Address}
*/
fromNulldata(data) {
return this.fromHash(data, 31);
}
/**
* Test whether the address is witness pubkeyhash.
* @returns {Boolean}
*/
isPubkeyhash() {
return this.version === 0 && this.hash.length === 20;
}
/**
* Test whether the address is witness scripthash.
* @returns {Boolean}
*/
isScripthash() {
return this.version === 0 && this.hash.length === 32;
}
/**
* Test whether the address is unspendable.
* @returns {Boolean}
*/
isNulldata() {
return this.version === 31;
}
/**
* Test whether the address is an unknown witness program.
* @returns {Boolean}
*/
isUnknown() {
switch (this.version) {
case 0:
return this.hash.length !== 20 && this.hash.length !== 32;
case 31:
return false;
}
return true;
}
/**
* Test address validity.
* @returns {Boolean}
*/
isValid() {
assert(this.version >= 0);
if (this.version > 31)
return false;
if (this.hash.length < 2 || this.hash.length > 40)
return false;
return true;
}
/**
* Calculate address size.
* @returns {Number}
*/
getSize() {
return 1 + 1 + this.hash.length;
}
/**
* Write address to buffer writer.
* @param {BufferWriter} bw
* @returns {BufferWriter}
*/
write(bw) {
bw.writeU8(this.version);
bw.writeU8(this.hash.length);
bw.writeBytes(this.hash);
return bw;
}
/**
* Read address from buffer reader.
* @param {BufferReader} br
* @returns {Address}
*/
read(br) {
const version = br.readU8();
assert(version <= 31);
const size = br.readU8();
assert(size >= 2 && size <= 40);
const hash = br.readBytes(size);
return this.fromHash(hash, version);
}
/**
* Inspect the Address.
* @returns {Object}
*/
format() {
return '<Address:'
+ ` version=${this.version}`
+ ` str=${this.toString()}`
+ '>';
}
/**
* Instantiate address from pubkey.
* @param {Buffer} key
* @returns {Address}
*/
static fromPubkey(key) {
return new this().fromPubkey(key);
}
/**
* Instantiate address from script.
* @param {Script} script
* @returns {Address}
*/
static fromScript(script) {
return new this().fromScript(script);
}
/**
* Create an Address from a witness.
* Attempt to extract address
* properties from a witness.
* @param {Witness}
* @returns {Address|null}
*/
static fromWitness(witness) {
return new this().fromWitness(witness);
}
/**
* Create a naked address from hash/version.
* @param {Hash} hash
* @param {Number} [version=-1]
* @returns {Address}
* @throws on bad hash size
*/
static fromHash(hash, version) {
return new this().fromHash(hash, version);
}
/**
* Instantiate address from witness pubkeyhash.
* @param {Buffer} hash
* @returns {Address}
*/
static fromPubkeyhash(hash) {
return new this().fromPubkeyhash(hash);
}
/**
* Instantiate address from witness scripthash.
* @param {Buffer} hash
* @returns {Address}
*/
static fromScripthash(hash) {
return new this().fromScripthash(hash);
}
/**
* Instantiate address from witness program.
* @param {Number} version
* @param {Buffer} hash
* @returns {Address}
*/
static fromProgram(version, hash) {
return new this().fromProgram(version, hash);
}
/**
* Instantiate address from nulldata.
* @param {Buffer} data
* @returns {Address}
*/
static fromNulldata(data) {
return new this().fromNulldata(data);
}
/**
* Get the hash of a base58 address or address-related object.
* @param {String|Address|Hash} data
* @param {Network?} network
* @returns {Hash}
*/
static getHash(data, network) {
if (!data)
throw new Error('Object is not an address.');
if (Buffer.isBuffer(data)) {
return data;
}
if (data instanceof Address)
return data.hash;
throw new Error('Object is not an address.');
}
}
/*
* Expose
*/
module.exports = Address;
}],
[/* 56 */ 'bcrypto', '/lib/encoding/bech32-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* bech32.js - bech32 for bcrypto
* Copyright (c) 2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(57 /* '../js/bech32' */);
}],
[/* 57 */ 'bcrypto', '/lib/js/bech32.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* bech32.js - bech32 for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on sipa/bech32:
* Copyright (c) 2017, Pieter Wuille (MIT License).
* https://github.com/sipa/bech32
*
* Resources:
* https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
* https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.c
* https://github.com/bitcoin/bitcoin/blob/master/src/bech32.cpp
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
/**
* Constants
*/
const POOL65 = Buffer.alloc(65);
const CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
const TABLE = [
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
15, -1, 10, 17, 21, 20, 26, 30,
7, 5, -1, -1, -1, -1, -1, -1,
-1, 29, -1, 24, 13, 25, 9, 8,
23, -1, 18, 22, 31, 27, 19, -1,
1, 0, 3, 16, 11, 28, 12, 14,
6, 4, 2, -1, -1, -1, -1, -1,
-1, 29, -1, 24, 13, 25, 9, 8,
23, -1, 18, 22, 31, 27, 19, -1,
1, 0, 3, 16, 11, 28, 12, 14,
6, 4, 2, -1, -1, -1, -1, -1
];
/**
* Update checksum.
* @ignore
* @param {Number} c
* @returns {Number}
*/
function polymod(c) {
const b = c >>> 25;
return ((c & 0x1ffffff) << 5)
^ (0x3b6a57b2 & -((b >> 0) & 1))
^ (0x26508e6d & -((b >> 1) & 1))
^ (0x1ea119fa & -((b >> 2) & 1))
^ (0x3d4233dd & -((b >> 3) & 1))
^ (0x2a1462b3 & -((b >> 4) & 1));
}
/**
* Encode hrp and data as a bech32 string.
* @param {String} hrp
* @param {Buffer} data
* @returns {String}
*/
function serialize(hrp, data) {
assert(typeof hrp === 'string');
assert(Buffer.isBuffer(data));
if (hrp.length === 0 || hrp.length > 83)
throw new Error('Invalid bech32 human-readable part.');
if (hrp.length + 1 + data.length + 6 > 90)
throw new Error('Invalid bech32 data length.');
let str = '';
let chk = 1;
let i;
for (i = 0; i < hrp.length; i++) {
const ch = hrp.charCodeAt(i);
if (ch < 33 || ch > 126)
throw new Error('Invalid bech32 character.');
if (ch >= 65 && ch <= 90)
throw new Error('Invalid bech32 character.');
chk = polymod(chk) ^ (ch >> 5);
}
chk = polymod(chk);
for (let i = 0; i < hrp.length; i++) {
const ch = hrp.charCodeAt(i);
chk = polymod(chk) ^ (ch & 0x1f);
str += hrp[i];
}
str += '1';
for (let i = 0; i < data.length; i++) {
const ch = data[i];
if (ch >> 5)
throw new Error('Invalid bech32 value.');
chk = polymod(chk) ^ ch;
str += CHARSET[ch];
}
for (let i = 0; i < 6; i++)
chk = polymod(chk);
chk ^= 1;
for (let i = 0; i < 6; i++)
str += CHARSET[(chk >>> ((5 - i) * 5)) & 0x1f];
return str;
}
/**
* Decode a bech32 string.
* @param {String} str
* @returns {Array} [hrp, data]
*/
function deserialize(str) {
assert(typeof str === 'string');
if (str.length < 8 || str.length > 90)
throw new Error('Invalid bech32 string length.');
let lower = false;
let upper = false;
let hlen = 0;
for (let i = 0; i < str.length; i++) {
const ch = str.charCodeAt(i);
if (ch < 33 || ch > 126)
throw new Error('Invalid bech32 character.');
if (ch >= 97 && ch <= 122)
lower = true;
else if (ch >= 65 && ch <= 90)
upper = true;
else if (ch === 49)
hlen = i;
}
if (hlen === 0)
throw new Error('Invalid bech32 human-readable part.');
const dlen = str.length - (hlen + 1);
if (dlen < 6)
throw new Error('Invalid bech32 data length.');
if (lower && upper)
throw new Error('Invalid bech32 casing.');
let chk = 1;
let hrp = '';
for (let i = 0; i < hlen; i++) {
let ch = str.charCodeAt(i);
if (ch >= 65 && ch <= 90)
ch += 32;
chk = polymod(chk) ^ (ch >> 5);
hrp += String.fromCharCode(ch);
}
chk = polymod(chk);
for (let i = 0; i < hlen; i++)
chk = polymod(chk) ^ (str.charCodeAt(i) & 0x1f);
const data = Buffer.alloc(dlen - 6);
let j = 0;
for (let i = hlen + 1; i < str.length; i++) {
const val = TABLE[str.charCodeAt(i)];
if (val === -1)
throw new Error('Invalid bech32 character.');
chk = polymod(chk) ^ val;
if (i < str.length - 6)
data[j++] = val;
}
if (chk !== 1)
throw new Error('Invalid bech32 checksum.');
assert(j === data.length);
return [hrp, data];
}
/**
* Test whether a string is a bech32 string.
* @param {String} str
* @returns {Boolean}
*/
function is(str) {
assert(typeof str === 'string');
try {
deserialize(str);
return true;
} catch (e) {
return false;
}
}
/**
* Convert serialized data to another base.
* @param {Buffer} dst
* @param {Number} dstoff
* @param {Number} dstbits
* @param {Buffer} src
* @param {Number} srcoff
* @param {Number} srcbits
* @param {Boolean} pad
* @returns {Buffer}
*/
function convert(dst, dstoff, dstbits, src, srcoff, srcbits, pad) {
assert(Buffer.isBuffer(dst));
assert((dstoff >>> 0) === dstoff);
assert((dstbits >>> 0) === dstbits);
assert(Buffer.isBuffer(src));
assert((srcoff >>> 0) === srcoff);
assert((srcbits >>> 0) === srcbits);
assert(typeof pad === 'boolean');
assert(dstbits >= 1 && dstbits <= 8);
assert(srcbits >= 1 && srcbits <= 8);
const mask = (1 << dstbits) - 1;
let acc = 0;
let bits = 0;
let i = srcoff;
let j = dstoff;
for (; i < src.length; i++) {
acc = (acc << srcbits) | src[i];
bits += srcbits;
while (bits >= dstbits) {
bits -= dstbits;
dst[j++] = (acc >>> bits) & mask;
}
}
const left = dstbits - bits;
if (pad) {
if (bits)
dst[j++] = (acc << left) & mask;
} else {
if (((acc << left) & mask) || bits >= srcbits)
throw new Error('Invalid bits.');
}
assert(j <= dst.length);
return dst.slice(0, j);
}
/**
* Calculate size required for bit conversion.
* @param {Number} len
* @param {Number} srcbits
* @param {Number} dstbits
* @param {Boolean} pad
* @returns {Number}
*/
function convertSize(len, srcbits, dstbits, pad) {
assert((len >>> 0) === len);
assert((srcbits >>> 0) === srcbits);
assert((dstbits >>> 0) === dstbits);
assert(typeof pad === 'boolean');
assert(srcbits >= 1 && srcbits <= 8);
assert(dstbits >= 1 && dstbits <= 8);
return ((len * srcbits + (dstbits - 1) * (pad | 0)) / dstbits) >>> 0;
}
/**
* Convert serialized data to another base.
* @param {Buffer} data
* @param {Number} srcbits
* @param {Number} dstbits
* @param {Boolean} pad
* @returns {Buffer}
*/
function convertBits(data, srcbits, dstbits, pad) {
assert(Buffer.isBuffer(data));
const size = convertSize(data.length, srcbits, dstbits, pad);
const out = Buffer.alloc(size);
return convert(out, 0, dstbits, data, 0, srcbits, pad);
}
/**
* Serialize data to bech32 address.
* @param {String} hrp
* @param {Number} version
* @param {Buffer} hash
* @returns {String}
*/
function encode(hrp, version, hash) {
assert(typeof hrp === 'string');
assert((version >>> 0) === version);
assert(Buffer.isBuffer(hash));
if (version > 31)
throw new Error('Invalid bech32 version.');
if (hash.length < 2 || hash.length > 40)
throw new Error('Invalid bech32 data length.');
const out = POOL65;
out[0] = version;
const data = convert(out, 1, 5, hash, 0, 8, true);
return serialize(hrp, data);
}
/**
* Deserialize data from bech32 address.
* @param {String} addr
* @returns {Array}
*/
function decode(addr) {
const [hrp, data] = deserialize(addr);
if (data.length === 0 || data.length > 65)
throw new Error('Invalid bech32 data length.');
const version = data[0];
if (version > 31)
throw new Error('Invalid bech32 version.');
const output = data; // Works because dstbits > srcbits.
const hash = convert(output, 0, 8, data, 1, 5, false);
if (hash.length < 2 || hash.length > 40)
throw new Error('Invalid bech32 data length.');
return [hrp, version, hash];
}
/**
* Test whether a string is a bech32 string.
* @param {String} addr
* @returns {Boolean}
*/
function test(addr) {
assert(typeof addr === 'string');
try {
decode(addr);
return true;
} catch (e) {
return false;
}
}
/*
* Expose
*/
exports.native = 0;
exports.serialize = serialize;
exports.deserialize = deserialize;
exports.is = is;
exports.convertBits = convertBits;
exports.encode = encode;
exports.decode = decode;
exports.test = test;
}],
[/* 58 */ 'bcrypto', '/lib/blake2b-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* blake2b.js - blake2b for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(59 /* './js/blake2b' */);
}],
[/* 59 */ 'bcrypto', '/lib/js/blake2b.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* blake2b.js - BLAKE2b implementation for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on dcposch/blakejs:
* Daniel Clemens Posch (CC0)
* https://github.com/dcposch/blakejs/blob/master/blake2b.js
*
* Resources:
* https://en.wikipedia.org/wiki/BLAKE_(hash_function)
* https://tools.ietf.org/html/rfc7693
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const HMAC = __node_require__(17 /* '../internal/hmac' */);
/*
* Constants
*/
const FINALIZED = 0x80000000;
const IV = new Uint32Array([
0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85,
0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a,
0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c,
0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19
]);
const SIGMA = new Uint8Array([
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x1c, 0x14, 0x08, 0x10, 0x12, 0x1e, 0x1a, 0x0c,
0x02, 0x18, 0x00, 0x04, 0x16, 0x0e, 0x0a, 0x06,
0x16, 0x10, 0x18, 0x00, 0x0a, 0x04, 0x1e, 0x1a,
0x14, 0x1c, 0x06, 0x0c, 0x0e, 0x02, 0x12, 0x08,
0x0e, 0x12, 0x06, 0x02, 0x1a, 0x18, 0x16, 0x1c,
0x04, 0x0c, 0x0a, 0x14, 0x08, 0x00, 0x1e, 0x10,
0x12, 0x00, 0x0a, 0x0e, 0x04, 0x08, 0x14, 0x1e,
0x1c, 0x02, 0x16, 0x18, 0x0c, 0x10, 0x06, 0x1a,
0x04, 0x18, 0x0c, 0x14, 0x00, 0x16, 0x10, 0x06,
0x08, 0x1a, 0x0e, 0x0a, 0x1e, 0x1c, 0x02, 0x12,
0x18, 0x0a, 0x02, 0x1e, 0x1c, 0x1a, 0x08, 0x14,
0x00, 0x0e, 0x0c, 0x06, 0x12, 0x04, 0x10, 0x16,
0x1a, 0x16, 0x0e, 0x1c, 0x18, 0x02, 0x06, 0x12,
0x0a, 0x00, 0x1e, 0x08, 0x10, 0x0c, 0x04, 0x14,
0x0c, 0x1e, 0x1c, 0x12, 0x16, 0x06, 0x00, 0x10,
0x18, 0x04, 0x1a, 0x0e, 0x02, 0x08, 0x14, 0x0a,
0x14, 0x04, 0x10, 0x08, 0x0e, 0x0c, 0x02, 0x0a,
0x1e, 0x16, 0x12, 0x1c, 0x06, 0x18, 0x1a, 0x00,
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x1c, 0x14, 0x08, 0x10, 0x12, 0x1e, 0x1a, 0x0c,
0x02, 0x18, 0x00, 0x04, 0x16, 0x0e, 0x0a, 0x06
]);
/**
* BLAKE2b
*/
class BLAKE2b {
constructor() {
this.state = new Uint32Array(16);
this.V = new Uint32Array(32);
this.M = new Uint32Array(32);
this.block = Buffer.alloc(128);
this.size = 32;
this.count = 0;
this.pos = FINALIZED;
}
init(size, key) {
if (size == null)
size = 32;
assert((size >>> 0) === size);
assert(key == null || Buffer.isBuffer(key));
if (size === 0 || size > 64)
throw new Error('Bad output length.');
if (key && key.length > 64)
throw new Error('Bad key length.');
const klen = key ? key.length : 0;
for (let i = 0; i < 16; i++)
this.state[i] = IV[i];
this.size = size;
this.count = 0;
this.pos = 0;
this.state[0] ^= 0x01010000 ^ (klen << 8) ^ this.size;
if (klen > 0) {
const block = Buffer.alloc(128, 0x00);
key.copy(block, 0);
this.update(block);
}
return this;
}
update(data) {
assert(Buffer.isBuffer(data));
assert(!(this.pos & FINALIZED), 'Context is not initialized.');
let off = 0;
let len = data.length;
if (len > 0) {
const left = this.pos;
const fill = 128 - left;
if (len > fill) {
this.pos = 0;
data.copy(this.block, left, off, off + fill);
this.count += 128;
this._compress(this.block, 0, false);
off += fill;
len -= fill;
while (len > 128) {
this.count += 128;
this._compress(data, off, false);
off += 128;
len -= 128;
}
}
data.copy(this.block, this.pos, off, off + len);
this.pos += len;
}
return this;
}
final() {
assert(!(this.pos & FINALIZED), 'Context is not initialized.');
this.count += this.pos;
this.block.fill(0, this.pos, 128);
this._compress(this.block, 0, true);
this.pos = FINALIZED;
const out = Buffer.alloc(this.size);
for (let i = 0; i < this.size; i++)
out[i] = this.state[i >>> 2] >>> (8 * (i & 3));
for (let i = 0; i < 16; i++)
this.state[i] = 0;
for (let i = 0; i < 32; i++) {
this.V[i] = 0;
this.M[i] = 0;
}
for (let i = 0; i < 128; i++)
this.block[i] = 0;
return out;
}
_compress(block, off, last) {
const {V, M} = this;
for (let i = 0; i < 16; i++) {
V[i] = this.state[i];
V[i + 16] = IV[i];
}
// uint128
V[24] ^= this.count;
V[25] ^= this.count * (1 / 0x100000000);
V[26] ^= 0;
V[27] ^= 0;
if (last) {
// last block
V[28] ^= -1;
V[29] ^= -1;
// last node
V[29] ^= 0;
V[30] ^= 0;
}
for (let i = 0; i < 32; i++) {
M[i] = readU32(block, off);
off += 4;
}
for (let i = 0; i < 12; i++) {
G(V, M, 0, 8, 16, 24, SIGMA[i * 16 + 0], SIGMA[i * 16 + 1]);
G(V, M, 2, 10, 18, 26, SIGMA[i * 16 + 2], SIGMA[i * 16 + 3]);
G(V, M, 4, 12, 20, 28, SIGMA[i * 16 + 4], SIGMA[i * 16 + 5]);
G(V, M, 6, 14, 22, 30, SIGMA[i * 16 + 6], SIGMA[i * 16 + 7]);
G(V, M, 0, 10, 20, 30, SIGMA[i * 16 + 8], SIGMA[i * 16 + 9]);
G(V, M, 2, 12, 22, 24, SIGMA[i * 16 + 10], SIGMA[i * 16 + 11]);
G(V, M, 4, 14, 16, 26, SIGMA[i * 16 + 12], SIGMA[i * 16 + 13]);
G(V, M, 6, 8, 18, 28, SIGMA[i * 16 + 14], SIGMA[i * 16 + 15]);
}
for (let i = 0; i < 16; i++)
this.state[i] ^= V[i] ^ V[i + 16];
}
static hash() {
return new BLAKE2b();
}
static hmac(size) {
return new HMAC(BLAKE2b, 128, [size]);
}
static digest(data, size, key) {
const {ctx} = BLAKE2b;
ctx.init(size, key);
ctx.update(data);
return ctx.final();
}
static root(left, right, size, key) {
if (size == null)
size = 32;
assert(Buffer.isBuffer(left) && left.length === size);
assert(Buffer.isBuffer(right) && right.length === size);
const {ctx} = BLAKE2b;
ctx.init(size, key);
ctx.update(left);
ctx.update(right);
return ctx.final();
}
static multi(x, y, z, size, key) {
const {ctx} = BLAKE2b;
ctx.init(size, key);
ctx.update(x);
ctx.update(y);
if (z)
ctx.update(z);
return ctx.final();
}
static mac(data, key, size) {
return BLAKE2b.hmac(size).init(key).update(data).final();
}
}
/*
* Static
*/
BLAKE2b.native = 0;
BLAKE2b.id = 'BLAKE2B256';
BLAKE2b.size = 32;
BLAKE2b.bits = 256;
BLAKE2b.blockSize = 128;
BLAKE2b.zero = Buffer.alloc(32, 0x00);
BLAKE2b.ctx = new BLAKE2b();
/*
* Helpers
*/
function sum64i(v, a, b) {
const o0 = v[a + 0] + v[b + 0];
const o1 = v[a + 1] + v[b + 1];
const c = (o0 >= 0x100000000) | 0;
v[a + 0] = o0;
v[a + 1] = o1 + c;
}
function sum64w(v, a, b0, b1) {
const o0 = v[a + 0] + b0;
const o1 = v[a + 1] + b1;
const c = (o0 >= 0x100000000) | 0;
v[a + 0] = o0;
v[a + 1] = o1 + c;
}
function G(v, m, a, b, c, d, ix, iy) {
const x0 = m[ix + 0];
const x1 = m[ix + 1];
const y0 = m[iy + 0];
const y1 = m[iy + 1];
sum64i(v, a, b);
sum64w(v, a, x0, x1);
const xor0 = v[d + 0] ^ v[a + 0];
const xor1 = v[d + 1] ^ v[a + 1];
v[d + 0] = xor1;
v[d + 1] = xor0;
sum64i(v, c, d);
const xor2 = v[b + 0] ^ v[c + 0];
const xor3 = v[b + 1] ^ v[c + 1];
v[b + 0] = (xor2 >>> 24) ^ (xor3 << 8);
v[b + 1] = (xor3 >>> 24) ^ (xor2 << 8);
sum64i(v, a, b);
sum64w(v, a, y0, y1);
const xor4 = v[d + 0] ^ v[a + 0];
const xor5 = v[d + 1] ^ v[a + 1];
v[d + 0] = (xor4 >>> 16) ^ (xor5 << 16);
v[d + 1] = (xor5 >>> 16) ^ (xor4 << 16);
sum64i(v, c, d);
const xor6 = v[b + 0] ^ v[c + 0];
const xor7 = v[b + 1] ^ v[c + 1];
v[b + 0] = (xor7 >>> 31) ^ (xor6 << 1);
v[b + 1] = (xor6 >>> 31) ^ (xor7 << 1);
}
function readU32(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off] * 0x1000000);
}
/*
* Expose
*/
module.exports = BLAKE2b;
}],
[/* 60 */ 'bcrypto', '/lib/sha3-browser.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* sha3.js - sha3 for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*/
'use strict';
module.exports = __node_require__(61 /* './js/sha3' */);
}],
[/* 61 */ 'bcrypto', '/lib/js/sha3.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* sha3.js - SHA3 implementation for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Resources:
* https://en.wikipedia.org/wiki/SHA-3
* https://keccak.team/specifications.html
* https://csrc.nist.gov/projects/hash-functions/sha-3-project/sha-3-standardization
* http://dx.doi.org/10.6028/NIST.FIPS.202
*/
'use strict';
const Keccak = __node_require__(62 /* './keccak' */);
/**
* SHA3
*/
class SHA3 extends Keccak {
constructor() {
super();
}
final() {
return super.final(0x06, null);
}
static hash() {
return new SHA3();
}
static hmac(bits) {
return super.hmac(bits, 0x06, null);
}
static digest(data, bits) {
return super.digest(data, bits, 0x06, null);
}
static root(left, right, bits) {
return super.root(left, right, bits, 0x06, null);
}
static multi(x, y, z, bits) {
return super.multi(x, y, z, bits, 0x06, null);
}
static mac(data, key, bits) {
return super.mac(data, key, bits, 0x06, null);
}
}
/*
* Static
*/
SHA3.native = 0;
SHA3.id = 'SHA3_256';
SHA3.size = 32;
SHA3.bits = 256;
SHA3.blockSize = 136;
SHA3.zero = Buffer.alloc(32, 0x00);
SHA3.ctx = new SHA3();
/*
* Expose
*/
module.exports = SHA3;
}],
[/* 62 */ 'bcrypto', '/lib/js/keccak.js', function(exports, module, __filename, __dirname, __meta) {
/*!
* keccak.js - Keccak/SHA3 implementation for bcrypto
* Copyright (c) 2017-2019, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcrypto
*
* Parts of this software are based on emn178/js-sha3:
* Copyright (c) 2015-2017, Chen, Yi-Cyuan (MIT License).
* https://github.com/emn178/js-sha3
*
* Parts of this software are based on rhash/RHash:
* Copyright (c) 2005-2014, Aleksey Kravchenko
* https://github.com/rhash/RHash
*
* Resources:
* https://en.wikipedia.org/wiki/SHA-3
* https://keccak.team/specifications.html
* https://csrc.nist.gov/projects/hash-functions/sha-3-project/sha-3-standardization
* http://dx.doi.org/10.6028/NIST.FIPS.202
* https://github.com/rhash/RHash/blob/master/librhash/sha3.c
* https://github.com/emn178/js-sha3/blob/master/src/sha3.js
*/
'use strict';
const assert = __node_require__(14 /* '../internal/assert' */);
const HMAC = __node_require__(17 /* '../internal/hmac' */);
/*
* Constants
*/
const FINALIZED = 0x80000000;
const ROUND_CONST = new Uint32Array([
0x00000001, 0x00000000, 0x00008082, 0x00000000,
0x0000808a, 0x80000000, 0x80008000, 0x80000000,
0x0000808b, 0x00000000, 0x80000001, 0x00000000,
0x80008081, 0x80000000, 0x00008009, 0x80000000,
0x0000008a, 0x00000000, 0x00000088, 0x00000000,
0x80008009, 0x00000000, 0x8000000a, 0x00000000,
0x8000808b, 0x00000000, 0x0000008b, 0x80000000,
0x00008089, 0x80000000, 0x00008003, 0x80000000,
0x00008002, 0x80000000, 0x00000080, 0x80000000,
0x0000800a, 0x00000000, 0x8000000a, 0x80000000,
0x80008081, 0x80000000, 0x00008080, 0x80000000,
0x80000001, 0x00000000, 0x80008008, 0x80000000
]);
/**
* Keccak
*/
class Keccak {
constructor() {
this.state = new Uint32Array(50);
this.block = Buffer.alloc(200);
this.bs = 136;
this.pos = FINALIZED;
}
init(bits) {
if (bits == null)
bits = 256;
assert((bits >>> 0) === bits);
assert(bits >= 128);
assert(bits <= 512);
const rate = 1600 - bits * 2;
assert(rate >= 0 && (rate & 63) === 0);
this.bs = rate >>> 3;
this.pos = 0;
return this;
}
update(data) {
assert(Buffer.isBuffer(data));
assert(!(this.pos & FINALIZED), 'Context is not initialized.');
let len = data.length;
let pos = this.pos;
let off = 0;
this.pos = (this.pos + len) % this.bs;
if (pos > 0) {
let want = this.bs - pos;
if (want > len)
want = len;
data.copy(this.block, pos, off, off + want);
pos += want;
len -= want;
off += want;
if (pos < this.bs)
return this;
this._transform(this.block, 0);
}
while (len >= this.bs) {
this._transform(data, off);
off += this.bs;
len -= this.bs;
}
if (len > 0)
data.copy(this.block, 0, off, off + len);
return this;
}
final(pad, len) {
if (pad == null)
pad = 0x01;
if (len == null || len === 0)
len = 100 - (this.bs >>> 1);
assert((pad & 0xff) === pad);
assert((len >>> 0) === len);
assert(!(this.pos & FINALIZED), 'Context is not initialized.');
this.block.fill(0, this.pos, this.bs);
this.block[this.pos] |= pad;
this.block[this.bs - 1] |= 0x80;
this._transform(this.block, 0);
this.pos = FINALIZED;
assert(len <= this.bs);
const out = Buffer.alloc(len);
for (let i = 0; i < len; i++)
out[i] = this.state[i >>> 2] >>> (8 * (i & 3));
for (let i = 0; i < 50; i++)
this.state[i] = 0;
for (let i = 0; i < this.bs; i++)
this.block[i] = 0;
return out;
}
_transform(block, off) {
const count = this.bs >>> 2;
const s = this.state;
for (let i = 0; i < count; i++)
s[i] ^= readU32(block, off + i * 4);
for (let n = 0; n < 48; n += 2) {
const c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
const c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
const c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42];
const c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43];
const c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44];
const c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45];
const c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46];
const c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47];
const c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48];
const c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49];
const h0 = c8 ^ ((c2 << 1) | (c3 >>> 31));
const l0 = c9 ^ ((c3 << 1) | (c2 >>> 31));
const h1 = c0 ^ ((c4 << 1) | (c5 >>> 31));
const l1 = c1 ^ ((c5 << 1) | (c4 >>> 31));
const h2 = c2 ^ ((c6 << 1) | (c7 >>> 31));
const l2 = c3 ^ ((c7 << 1) | (c6 >>> 31));
const h3 = c4 ^ ((c8 << 1) | (c9 >>> 31));
const l3 = c5 ^ ((c9 << 1) | (c8 >>> 31));
const h4 = c6 ^ ((c0 << 1) | (c1 >>> 31));
const l4 = c7 ^ ((c1 << 1) | (c0 >>> 31));
s[0] ^= h0;
s[1] ^= l0;
s[10] ^= h0;
s[11] ^= l0;
s[20] ^= h0;
s[21] ^= l0;
s[30] ^= h0;
s[31] ^= l0;
s[40] ^= h0;
s[41] ^= l0;
s[2] ^= h1;
s[3] ^= l1;
s[12] ^= h1;
s[13] ^= l1;
s[22] ^= h1;
s[23] ^= l1;
s[32] ^= h1;
s[33] ^= l1;
s[42] ^= h1;
s[43] ^= l1;
s[4] ^= h2;
s[5] ^= l2;
s[14] ^= h2;
s[15] ^= l2;
s[24] ^= h2;
s[25] ^= l2;
s[34] ^= h2;
s[35] ^= l2;
s[44] ^= h2;
s[45] ^= l2;
s[6] ^= h3;
s[7] ^= l3;
s[16] ^= h3;
s[17] ^= l3;
s[26] ^= h3;
s[27] ^= l3;
s[36] ^= h3;
s[37] ^= l3;
s[46] ^= h3;
s[47] ^= l3;
s[8] ^= h4;
s[9] ^= l4;
s[18] ^= h4;
s[19] ^= l4;
s[28] ^= h4;
s[29] ^= l4;
s[38] ^= h4;
s[39] ^= l4;
s[48] ^= h4;
s[49] ^= l4;
const b0 = s[0];
const b1 = s[1];
const b32 = (s[11] << 4) | (s[10] >>> 28);
const b33 = (s[10] << 4) | (s[11] >>> 28);
const b14 = (s[20] << 3) | (s[21] >>> 29);
const b15 = (s[21] << 3) | (s[20] >>> 29);
const b46 = (s[31] << 9) | (s[30] >>> 23);
const b47 = (s[30] << 9) | (s[31] >>> 23);
const b28 = (s[40] << 18) | (s[41] >>> 14);
const b29 = (s[41] << 18) | (s[40] >>> 14);
const b20 = (s[2] << 1) | (s[3] >>> 31);
const b21 = (s[3] << 1) | (s[2] >>> 31);
const b2 = (s[13] << 12) | (s[12] >>> 20);
const b3 = (s[12] << 12) | (s[13] >>> 20);
const b34 = (s[22] << 10) | (s[23] >>> 22);
const b35 = (s[23] << 10) | (s[22] >>> 22);
const b16 = (s[33] << 13) | (s[32] >>> 19);
const b17 = (s[32] << 13) | (s[33] >>> 19);
const b48 = (s[42] << 2) | (s[43] >>> 30);
const b49 = (s[43] << 2) | (s[42] >>> 30);
const b40 = (s[5] << 30) | (s[4] >>> 2);
const b41 = (s[4] << 30) | (s[5] >>> 2);
const b22 = (s[14] << 6) | (s[15] >>> 26);
const b23 = (s[15] << 6) | (s[14] >>> 26);
const b4 = (s[25] << 11) | (s[24] >>> 21);
const b5 = (s[24] << 11) | (s[25] >>> 21);
const b36 = (s[34] << 15) | (s[35] >>> 17);
const b37 = (s[35] << 15) | (s[34] >>> 17);
const b18 = (s[45] << 29) | (s[44] >>> 3);
const b19 = (s[44] << 29) | (s[45] >>> 3);
const b10 = (s[6] << 28) | (s[7] >>> 4);
const b11 = (s[7] << 28) | (s[6] >>> 4);
const b42 = (s[17] << 23) | (s[16] >>> 9);
const b43 = (s[16] << 23) | (s[17] >>> 9);
const b24 = (s[26] << 25) | (s[27] >>> 7);
const b25 = (s[27] << 25) | (s[26] >>> 7);
const b6 = (s[36] << 21) | (s[37] >>> 11);
const b7 = (s[37] << 21) | (s[36] >>> 11);
const b38 = (s[47] << 24) | (s[46] >>> 8);
const b39 = (s[46] << 24) | (s[47] >>> 8);
const b30 = (s[8] << 27) | (s[9] >>> 5);
const b31 = (s[9] << 27) | (s[8] >>> 5);
const b12 = (s[18] << 20) | (s[19] >>> 12);
const b13 = (s[19] << 20) | (s[18] >>> 12);
const b44 = (s[29] << 7) | (s[28] >>> 25);
const b45 = (s[28] << 7) | (s[29] >>> 25);
const b26 = (s[38] << 8) | (s[39] >>> 24);
const b27 = (s[39] << 8) | (s[38] >>> 24);
const b8 = (s[48] << 14) | (s[49] >>> 18);
const b9 = (s[49] << 14) | (s[48] >>> 18);
s[0] = b0 ^ (~b2 & b4);
s[1] = b1 ^ (~b3 & b5);
s[10] = b10 ^ (~b12 & b14);
s[11] = b11 ^ (~b13 & b15);
s[20] = b20 ^ (~b22 & b24);
s[21] = b21 ^ (~b23 & b25);
s[30] = b30 ^ (~b32 & b34);
s[31] = b31 ^ (~b33 & b35);
s[40] = b40 ^ (~b42 & b44);
s[41] = b41 ^ (~b43 & b45);
s[2] = b2 ^ (~b4 & b6);
s[3] = b3 ^ (~b5 & b7);
s[12] = b12 ^ (~b14 & b16);
s[13] = b13 ^ (~b15 & b17);
s[22] = b22 ^ (~b24 & b26);
s[23] = b23 ^ (~b25 & b27);
s[32] = b32 ^ (~b34 & b36);
s[33] = b33 ^ (~b35 & b37);
s[42] = b42 ^ (~b44 & b46);
s[43] = b43 ^ (~b45 & b47);
s[4] = b4 ^ (~b6 & b8);
s[5] = b5 ^ (~b7 & b9);
s[14] = b14 ^ (~b16 & b18);
s[15] = b15 ^ (~b17 & b19);
s[24] = b24 ^ (~b26 & b28);
s[25] = b25 ^ (~b27 & b29);
s[34] = b34 ^ (~b36 & b38);
s[35] = b35 ^ (~b37 & b39);
s[44] = b44 ^ (~b46 & b48);
s[45] = b45 ^ (~b47 & b49);
s[6] = b6 ^ (~b8 & b0);
s[7] = b7 ^ (~b9 & b1);
s[16] = b16 ^ (~b18 & b10);
s[17] = b17 ^ (~b19 & b11);
s[26] = b26 ^ (~b28 & b20);
s[27] = b27 ^ (~b29 & b21);
s[36] = b36 ^ (~b38 & b30);
s[37] = b37 ^ (~b39 & b31);
s[46] = b46 ^ (~b48 & b40);
s[47] = b47 ^ (~b49 & b41);
s[8] = b8 ^ (~b0 & b2);
s[9] = b9 ^ (~b1 & b3);
s[18] = b18 ^ (~b10 & b12);
s[19] = b19 ^ (~b11 & b13);
s[28] = b28 ^ (~b20 & b22);
s[29] = b29 ^ (~b21 & b23);
s[38] = b38 ^ (~b30 & b32);
s[39] = b39 ^ (~b31 & b33);
s[48] = b48 ^ (~b40 & b42);
s[49] = b49 ^ (~b41 & b43);
s[0] ^= ROUND_CONST[n + 0];
s[1] ^= ROUND_CONST[n + 1];
}
}
static hash() {
return new Keccak();
}
static hmac(bits, pad, len) {
if (bits == null)
bits = 256;
assert((bits >>> 0) === bits);
const rate = 1600 - bits * 2;
assert(rate >= 0 && (rate & 63) === 0);
return new HMAC(Keccak, rate >>> 3, [bits], [pad, len]);
}
static digest(data, bits, pad, len) {
return Keccak.ctx.init(bits).update(data).final(pad, len);
}
static root(left, right, bits, pad, len) {
if (bits == null)
bits = 256;
if (len == null)
len = 0;
if (len === 0)
len = bits >>> 3;
assert((bits >>> 0) === bits);
assert((bits & 7) === 0);
assert((len >>> 0) === len);
assert(Buffer.isBuffer(left) && left.length === len);
assert(Buffer.isBuffer(right) && right.length === len);
return Keccak.ctx.init(bits).update(left).update(right).final(pad, len);
}
static multi(x, y, z, bits, pad, len) {
const {ctx} = Keccak;
ctx.init(bits);
ctx.update(x);
ctx.update(y);
if (z)
ctx.update(z);
return ctx.final(pad, len);
}
static mac(data, key, bits, pad, len) {
return Keccak.hmac(bits, pad, len).init(key).update(data).final();
}
}
/*
* Static
*/
Keccak.native = 0;
Keccak.id = 'KECCAK256';
Keccak.size = 32;
Keccak.bits = 256;
Keccak.blockSize = 136;
Keccak.zero = Buffer.alloc(32, 0x00);
Keccak.ctx = new Keccak();
/*
* Helpers
*/
function readU32(data, off) {
return (data[off++]
+ data[off++] * 0x100
+ data[off++] * 0x10000
+ data[off] * 0x1000000);
}
/*
* Expose
*/
module.exports = Keccak;
}]
];
var __node_cache__ = [];
function __node_error__(location) {
var err = new Error('Cannot find module \'' + location + '\'');
err.code = 'MODULE_NOT_FOUND';
throw err;
}
function __node_require__(id) {
if ((id >>> 0) !== id || id > __node_modules__.length)
return __node_error__(id);
while (__node_cache__.length <= id)
__node_cache__.push(null);
var cache = __node_cache__[id];
if (cache)
return cache.exports;
var mod = __node_modules__[id];
var name = mod[0];
var path = mod[1];
var func = mod[2];
var meta;
var _exports = exports;
var _module = module;
if (id !== 0) {
_exports = {};
_module = {
id: '/' + name + path,
exports: _exports,
parent: module.parent,
filename: module.filename,
loaded: false,
children: module.children,
paths: module.paths
};
}
__node_cache__[id] = _module;
try {
func.call(_exports, _exports, _module,
__filename, __dirname, meta);
} catch (e) {
__node_cache__[id] = null;
throw e;
}
__node_modules__[id] = null;
if (id !== 0)
_module.loaded = true;
return _module.exports;
}
__node_require__(0);