@waku/enr
Version:
ENR (EIP-778) for Waku
1,629 lines (1,588 loc) โข 432 kB
JavaScript
// Maximum encoded size of an ENR
const MAX_RECORD_SIZE = 300;
const ERR_INVALID_ID = "Invalid record id";
const ERR_NO_SIGNATURE = "No valid signature found";
// The maximum length of byte size of a multiaddr to encode in the `multiaddr` field
// The size is a big endian 16-bit unsigned integer
const MULTIADDR_LENGTH_SIZE = 2;
function equals$2(aa, bb) {
if (aa === bb) {
return true;
}
if (aa.byteLength !== bb.byteLength) {
return false;
}
for (let ii = 0; ii < aa.byteLength; ii++) {
if (aa[ii] !== bb[ii]) {
return false;
}
}
return true;
}
function coerce(o) {
if (o instanceof Uint8Array && o.constructor.name === 'Uint8Array') {
return o;
}
if (o instanceof ArrayBuffer) {
return new Uint8Array(o);
}
if (ArrayBuffer.isView(o)) {
return new Uint8Array(o.buffer, o.byteOffset, o.byteLength);
}
throw new Error('Unknown type, must be binary type');
}
function fromString$1(str) {
return new TextEncoder().encode(str);
}
function toString$1(b) {
return new TextDecoder().decode(b);
}
/* eslint-disable */
// base-x encoding / decoding
// Copyright (c) 2018 base-x contributors
// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
// Distributed under the MIT software license, see the accompanying
// file LICENSE or http://www.opensource.org/licenses/mit-license.php.
/**
* @param {string} ALPHABET
* @param {any} name
*/
function base(ALPHABET, name) {
if (ALPHABET.length >= 255) {
throw new TypeError('Alphabet too long');
}
var BASE_MAP = new Uint8Array(256);
for (var j = 0; j < BASE_MAP.length; j++) {
BASE_MAP[j] = 255;
}
for (var i = 0; i < ALPHABET.length; i++) {
var x = ALPHABET.charAt(i);
var xc = x.charCodeAt(0);
if (BASE_MAP[xc] !== 255) {
throw new TypeError(x + ' is ambiguous');
}
BASE_MAP[xc] = i;
}
var BASE = ALPHABET.length;
var LEADER = ALPHABET.charAt(0);
var FACTOR = Math.log(BASE) / Math.log(256); // log(BASE) / log(256), rounded up
var iFACTOR = Math.log(256) / Math.log(BASE); // log(256) / log(BASE), rounded up
/**
* @param {any[] | Iterable<number>} source
*/
function encode(source) {
// @ts-ignore
if (source instanceof Uint8Array)
;
else if (ArrayBuffer.isView(source)) {
source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
}
else if (Array.isArray(source)) {
source = Uint8Array.from(source);
}
if (!(source instanceof Uint8Array)) {
throw new TypeError('Expected Uint8Array');
}
if (source.length === 0) {
return '';
}
// Skip & count leading zeroes.
var zeroes = 0;
var length = 0;
var pbegin = 0;
var pend = source.length;
while (pbegin !== pend && source[pbegin] === 0) {
pbegin++;
zeroes++;
}
// Allocate enough space in big-endian base58 representation.
var size = ((pend - pbegin) * iFACTOR + 1) >>> 0;
var b58 = new Uint8Array(size);
// Process the bytes.
while (pbegin !== pend) {
var carry = source[pbegin];
// Apply "b58 = b58 * 256 + ch".
var i = 0;
for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {
carry += (256 * b58[it1]) >>> 0;
b58[it1] = (carry % BASE) >>> 0;
carry = (carry / BASE) >>> 0;
}
if (carry !== 0) {
throw new Error('Non-zero carry');
}
length = i;
pbegin++;
}
// Skip leading zeroes in base58 result.
var it2 = size - length;
while (it2 !== size && b58[it2] === 0) {
it2++;
}
// Translate the result into a string.
var str = LEADER.repeat(zeroes);
for (; it2 < size; ++it2) {
str += ALPHABET.charAt(b58[it2]);
}
return str;
}
/**
* @param {string | string[]} source
*/
function decodeUnsafe(source) {
if (typeof source !== 'string') {
throw new TypeError('Expected String');
}
if (source.length === 0) {
return new Uint8Array();
}
var psz = 0;
// Skip leading spaces.
if (source[psz] === ' ') {
return;
}
// Skip and count leading '1's.
var zeroes = 0;
var length = 0;
while (source[psz] === LEADER) {
zeroes++;
psz++;
}
// Allocate enough space in big-endian base256 representation.
var size = (((source.length - psz) * FACTOR) + 1) >>> 0; // log(58) / log(256), rounded up.
var b256 = new Uint8Array(size);
// Process the characters.
while (source[psz]) {
// Decode character
var carry = BASE_MAP[source.charCodeAt(psz)];
// Invalid character
if (carry === 255) {
return;
}
var i = 0;
for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {
carry += (BASE * b256[it3]) >>> 0;
b256[it3] = (carry % 256) >>> 0;
carry = (carry / 256) >>> 0;
}
if (carry !== 0) {
throw new Error('Non-zero carry');
}
length = i;
psz++;
}
// Skip trailing spaces.
if (source[psz] === ' ') {
return;
}
// Skip leading zeroes in b256.
var it4 = size - length;
while (it4 !== size && b256[it4] === 0) {
it4++;
}
var vch = new Uint8Array(zeroes + (size - it4));
var j = zeroes;
while (it4 !== size) {
vch[j++] = b256[it4++];
}
return vch;
}
/**
* @param {string | string[]} string
*/
function decode(string) {
var buffer = decodeUnsafe(string);
if (buffer) {
return buffer;
}
throw new Error(`Non-${name} character`);
}
return {
encode: encode,
decodeUnsafe: decodeUnsafe,
decode: decode
};
}
var src = base;
var _brrp__multiformats_scope_baseX = src;
/**
* Class represents both BaseEncoder and MultibaseEncoder meaning it
* can be used to encode to multibase or base encode without multibase
* prefix.
*/
class Encoder {
name;
prefix;
baseEncode;
constructor(name, prefix, baseEncode) {
this.name = name;
this.prefix = prefix;
this.baseEncode = baseEncode;
}
encode(bytes) {
if (bytes instanceof Uint8Array) {
return `${this.prefix}${this.baseEncode(bytes)}`;
}
else {
throw Error('Unknown type, must be binary type');
}
}
}
/**
* Class represents both BaseDecoder and MultibaseDecoder so it could be used
* to decode multibases (with matching prefix) or just base decode strings
* with corresponding base encoding.
*/
class Decoder {
name;
prefix;
baseDecode;
prefixCodePoint;
constructor(name, prefix, baseDecode) {
this.name = name;
this.prefix = prefix;
const prefixCodePoint = prefix.codePointAt(0);
/* c8 ignore next 3 */
if (prefixCodePoint === undefined) {
throw new Error('Invalid prefix character');
}
this.prefixCodePoint = prefixCodePoint;
this.baseDecode = baseDecode;
}
decode(text) {
if (typeof text === 'string') {
if (text.codePointAt(0) !== this.prefixCodePoint) {
throw Error(`Unable to decode multibase string ${JSON.stringify(text)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`);
}
return this.baseDecode(text.slice(this.prefix.length));
}
else {
throw Error('Can only multibase decode strings');
}
}
or(decoder) {
return or(this, decoder);
}
}
class ComposedDecoder {
decoders;
constructor(decoders) {
this.decoders = decoders;
}
or(decoder) {
return or(this, decoder);
}
decode(input) {
const prefix = input[0];
const decoder = this.decoders[prefix];
if (decoder != null) {
return decoder.decode(input);
}
else {
throw RangeError(`Unable to decode multibase string ${JSON.stringify(input)}, only inputs prefixed with ${Object.keys(this.decoders)} are supported`);
}
}
}
function or(left, right) {
return new ComposedDecoder({
...(left.decoders ?? { [left.prefix]: left }),
...(right.decoders ?? { [right.prefix]: right })
});
}
class Codec {
name;
prefix;
baseEncode;
baseDecode;
encoder;
decoder;
constructor(name, prefix, baseEncode, baseDecode) {
this.name = name;
this.prefix = prefix;
this.baseEncode = baseEncode;
this.baseDecode = baseDecode;
this.encoder = new Encoder(name, prefix, baseEncode);
this.decoder = new Decoder(name, prefix, baseDecode);
}
encode(input) {
return this.encoder.encode(input);
}
decode(input) {
return this.decoder.decode(input);
}
}
function from$1({ name, prefix, encode, decode }) {
return new Codec(name, prefix, encode, decode);
}
function baseX({ name, prefix, alphabet }) {
const { encode, decode } = _brrp__multiformats_scope_baseX(alphabet, name);
return from$1({
prefix,
name,
encode,
decode: (text) => coerce(decode(text))
});
}
function decode$6(string, alphabetIdx, bitsPerChar, name) {
// Count the padding bytes:
let end = string.length;
while (string[end - 1] === '=') {
--end;
}
// Allocate the output:
const out = new Uint8Array((end * bitsPerChar / 8) | 0);
// Parse the data:
let bits = 0; // Number of bits currently in the buffer
let buffer = 0; // Bits waiting to be written out, MSB first
let written = 0; // Next byte to write
for (let i = 0; i < end; ++i) {
// Read one character from the string:
const value = alphabetIdx[string[i]];
if (value === undefined) {
throw new SyntaxError(`Non-${name} character`);
}
// Append the bits to the buffer:
buffer = (buffer << bitsPerChar) | value;
bits += bitsPerChar;
// Write out some bits if the buffer has a byte's worth:
if (bits >= 8) {
bits -= 8;
out[written++] = 0xff & (buffer >> bits);
}
}
// Verify that we have received just enough bits:
if (bits >= bitsPerChar || (0xff & (buffer << (8 - bits))) !== 0) {
throw new SyntaxError('Unexpected end of data');
}
return out;
}
function encode$4(data, alphabet, bitsPerChar) {
const pad = alphabet[alphabet.length - 1] === '=';
const mask = (1 << bitsPerChar) - 1;
let out = '';
let bits = 0; // Number of bits currently in the buffer
let buffer = 0; // Bits waiting to be written out, MSB first
for (let i = 0; i < data.length; ++i) {
// Slurp data into the buffer:
buffer = (buffer << 8) | data[i];
bits += 8;
// Write out as much as we can:
while (bits > bitsPerChar) {
bits -= bitsPerChar;
out += alphabet[mask & (buffer >> bits)];
}
}
// Partial character:
if (bits !== 0) {
out += alphabet[mask & (buffer << (bitsPerChar - bits))];
}
// Add padding characters until we hit a byte boundary:
if (pad) {
while (((out.length * bitsPerChar) & 7) !== 0) {
out += '=';
}
}
return out;
}
function createAlphabetIdx(alphabet) {
// Build the character lookup table:
const alphabetIdx = {};
for (let i = 0; i < alphabet.length; ++i) {
alphabetIdx[alphabet[i]] = i;
}
return alphabetIdx;
}
/**
* RFC4648 Factory
*/
function rfc4648({ name, prefix, bitsPerChar, alphabet }) {
const alphabetIdx = createAlphabetIdx(alphabet);
return from$1({
prefix,
name,
encode(input) {
return encode$4(input, alphabet, bitsPerChar);
},
decode(input) {
return decode$6(input, alphabetIdx, bitsPerChar, name);
}
});
}
const base10 = baseX({
prefix: '9',
name: 'base10',
alphabet: '0123456789'
});
var base10$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base10: base10
});
const base16 = rfc4648({
prefix: 'f',
name: 'base16',
alphabet: '0123456789abcdef',
bitsPerChar: 4
});
const base16upper = rfc4648({
prefix: 'F',
name: 'base16upper',
alphabet: '0123456789ABCDEF',
bitsPerChar: 4
});
var base16$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base16: base16,
base16upper: base16upper
});
const base2 = rfc4648({
prefix: '0',
name: 'base2',
alphabet: '01',
bitsPerChar: 1
});
var base2$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base2: base2
});
const alphabet = Array.from('๐๐ชโ๐ฐ๐๐๐๐๐๐๐๐๐๐๐๐๐โ๐ป๐ฅ๐พ๐ฟ๐โค๐๐คฃ๐๐๐๐ญ๐๐๐
๐๐๐ฅ๐ฅฐ๐๐๐๐ข๐ค๐๐๐ช๐โบ๐๐ค๐๐๐๐๐น๐คฆ๐๐โโจ๐คท๐ฑ๐๐ธ๐๐๐๐๐๐๐๐๐คฉ๐๐๐ค๐๐ฏ๐๐๐ถ๐๐คญโฃ๐๐๐๐ช๐๐ฅ๐๐๐ฉ๐ก๐คช๐๐ฅณ๐ฅ๐คค๐๐๐ณโ๐๐๐ด๐๐ฌ๐๐๐ท๐ป๐โญโ
๐ฅบ๐๐๐ค๐ฆโ๐ฃ๐๐โน๐๐๐ โ๐๐บ๐๐ป๐๐๐๐๐น๐ฃ๐ซ๐๐๐ต๐ค๐๐ด๐ค๐ผ๐ซโฝ๐คโ๐๐คซ๐๐ฎ๐๐ป๐๐ถ๐๐ฒ๐ฟ๐งก๐โก๐๐โโ๐๐ฐ๐คจ๐ถ๐ค๐ถ๐ฐ๐๐ข๐ค๐๐จ๐จ๐คฌโ๐๐บ๐ค๐๐๐ฑ๐๐ถ๐ฅดโถโกโ๐๐ธโฌ๐จ๐๐ฆ๐ท๐บโ ๐
๐๐ต๐๐คฒ๐ค ๐คง๐๐ต๐
๐ง๐พ๐๐๐ค๐๐คฏ๐ทโ๐ง๐ฏ๐๐๐ค๐๐โ๐ด๐ฃ๐ธ๐๐๐ฅ๐คข๐
๐ก๐ฉ๐๐ธ๐ป๐ค๐คฎ๐ผ๐ฅต๐ฉ๐๐๐ผ๐๐ฃ๐ฅ');
const alphabetBytesToChars = (alphabet.reduce((p, c, i) => { p[i] = c; return p; }, ([])));
const alphabetCharsToBytes = (alphabet.reduce((p, c, i) => {
const codePoint = c.codePointAt(0);
if (codePoint == null) {
throw new Error(`Invalid character: ${c}`);
}
p[codePoint] = i;
return p;
}, ([])));
function encode$3(data) {
return data.reduce((p, c) => {
p += alphabetBytesToChars[c];
return p;
}, '');
}
function decode$5(str) {
const byts = [];
for (const char of str) {
const codePoint = char.codePointAt(0);
if (codePoint == null) {
throw new Error(`Invalid character: ${char}`);
}
const byt = alphabetCharsToBytes[codePoint];
if (byt == null) {
throw new Error(`Non-base256emoji character: ${char}`);
}
byts.push(byt);
}
return new Uint8Array(byts);
}
const base256emoji = from$1({
prefix: '๐',
name: 'base256emoji',
encode: encode$3,
decode: decode$5
});
var base256emoji$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base256emoji: base256emoji
});
const base32 = rfc4648({
prefix: 'b',
name: 'base32',
alphabet: 'abcdefghijklmnopqrstuvwxyz234567',
bitsPerChar: 5
});
const base32upper = rfc4648({
prefix: 'B',
name: 'base32upper',
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
bitsPerChar: 5
});
const base32pad = rfc4648({
prefix: 'c',
name: 'base32pad',
alphabet: 'abcdefghijklmnopqrstuvwxyz234567=',
bitsPerChar: 5
});
const base32padupper = rfc4648({
prefix: 'C',
name: 'base32padupper',
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=',
bitsPerChar: 5
});
const base32hex = rfc4648({
prefix: 'v',
name: 'base32hex',
alphabet: '0123456789abcdefghijklmnopqrstuv',
bitsPerChar: 5
});
const base32hexupper = rfc4648({
prefix: 'V',
name: 'base32hexupper',
alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUV',
bitsPerChar: 5
});
const base32hexpad = rfc4648({
prefix: 't',
name: 'base32hexpad',
alphabet: '0123456789abcdefghijklmnopqrstuv=',
bitsPerChar: 5
});
const base32hexpadupper = rfc4648({
prefix: 'T',
name: 'base32hexpadupper',
alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUV=',
bitsPerChar: 5
});
const base32z = rfc4648({
prefix: 'h',
name: 'base32z',
alphabet: 'ybndrfg8ejkmcpqxot1uwisza345h769',
bitsPerChar: 5
});
var base32$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base32: base32,
base32hex: base32hex,
base32hexpad: base32hexpad,
base32hexpadupper: base32hexpadupper,
base32hexupper: base32hexupper,
base32pad: base32pad,
base32padupper: base32padupper,
base32upper: base32upper,
base32z: base32z
});
const base36 = baseX({
prefix: 'k',
name: 'base36',
alphabet: '0123456789abcdefghijklmnopqrstuvwxyz'
});
const base36upper = baseX({
prefix: 'K',
name: 'base36upper',
alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
});
var base36$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base36: base36,
base36upper: base36upper
});
const base58btc = baseX({
name: 'base58btc',
prefix: 'z',
alphabet: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
});
const base58flickr = baseX({
name: 'base58flickr',
prefix: 'Z',
alphabet: '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
});
var base58 = /*#__PURE__*/Object.freeze({
__proto__: null,
base58btc: base58btc,
base58flickr: base58flickr
});
const base64 = rfc4648({
prefix: 'm',
name: 'base64',
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
bitsPerChar: 6
});
const base64pad = rfc4648({
prefix: 'M',
name: 'base64pad',
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
bitsPerChar: 6
});
const base64url = rfc4648({
prefix: 'u',
name: 'base64url',
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
bitsPerChar: 6
});
const base64urlpad = rfc4648({
prefix: 'U',
name: 'base64urlpad',
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=',
bitsPerChar: 6
});
var base64$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base64: base64,
base64pad: base64pad,
base64url: base64url,
base64urlpad: base64urlpad
});
const base8 = rfc4648({
prefix: '7',
name: 'base8',
alphabet: '01234567',
bitsPerChar: 3
});
var base8$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base8: base8
});
const identity$1 = from$1({
prefix: '\x00',
name: 'identity',
encode: (buf) => toString$1(buf),
decode: (str) => fromString$1(str)
});
var identityBase = /*#__PURE__*/Object.freeze({
__proto__: null,
identity: identity$1
});
new TextEncoder();
new TextDecoder();
/* eslint-disable */
var encode_1 = encode$2;
var MSB$1 = 0x80, MSBALL = -128, INT = Math.pow(2, 31);
/**
* @param {number} num
* @param {number[]} out
* @param {number} offset
*/
function encode$2(num, out, offset) {
out = out || [];
offset = offset || 0;
var oldOffset = offset;
while (num >= INT) {
out[offset++] = (num & 0xFF) | MSB$1;
num /= 128;
}
while (num & MSBALL) {
out[offset++] = (num & 0xFF) | MSB$1;
num >>>= 7;
}
out[offset] = num | 0;
// @ts-ignore
encode$2.bytes = offset - oldOffset + 1;
return out;
}
var decode$4 = read$1;
var MSB$1$1 = 0x80, REST$1 = 0x7F;
/**
* @param {string | any[]} buf
* @param {number} offset
*/
function read$1(buf, offset) {
var res = 0, offset = offset || 0, shift = 0, counter = offset, b, l = buf.length;
do {
if (counter >= l) {
// @ts-ignore
read$1.bytes = 0;
throw new RangeError('Could not decode varint');
}
b = buf[counter++];
res += shift < 28
? (b & REST$1) << shift
: (b & REST$1) * Math.pow(2, shift);
shift += 7;
} while (b >= MSB$1$1);
// @ts-ignore
read$1.bytes = counter - offset;
return res;
}
var N1$1 = Math.pow(2, 7);
var N2$1 = Math.pow(2, 14);
var N3$1 = Math.pow(2, 21);
var N4$1 = Math.pow(2, 28);
var N5$1 = Math.pow(2, 35);
var N6$1 = Math.pow(2, 42);
var N7$1 = Math.pow(2, 49);
var N8 = Math.pow(2, 56);
var N9 = Math.pow(2, 63);
var length$1 = function (/** @type {number} */ value) {
return (value < N1$1 ? 1
: value < N2$1 ? 2
: value < N3$1 ? 3
: value < N4$1 ? 4
: value < N5$1 ? 5
: value < N6$1 ? 6
: value < N7$1 ? 7
: value < N8 ? 8
: value < N9 ? 9
: 10);
};
var varint = {
encode: encode_1,
decode: decode$4,
encodingLength: length$1
};
var _brrp_varint = varint;
function decode$3(data, offset = 0) {
const code = _brrp_varint.decode(data, offset);
return [code, _brrp_varint.decode.bytes];
}
function encodeTo(int, target, offset = 0) {
_brrp_varint.encode(int, target, offset);
return target;
}
function encodingLength$1(int) {
return _brrp_varint.encodingLength(int);
}
/**
* Creates a multihash digest.
*/
function create(code, digest) {
const size = digest.byteLength;
const sizeOffset = encodingLength$1(code);
const digestOffset = sizeOffset + encodingLength$1(size);
const bytes = new Uint8Array(digestOffset + size);
encodeTo(code, bytes, 0);
encodeTo(size, bytes, sizeOffset);
bytes.set(digest, digestOffset);
return new Digest(code, size, digest, bytes);
}
/**
* Turns bytes representation of multihash digest into an instance.
*/
function decode$2(multihash) {
const bytes = coerce(multihash);
const [code, sizeOffset] = decode$3(bytes);
const [size, digestOffset] = decode$3(bytes.subarray(sizeOffset));
const digest = bytes.subarray(sizeOffset + digestOffset);
if (digest.byteLength !== size) {
throw new Error('Incorrect length');
}
return new Digest(code, size, digest, bytes);
}
function equals$1(a, b) {
if (a === b) {
return true;
}
else {
const data = b;
return (a.code === data.code &&
a.size === data.size &&
data.bytes instanceof Uint8Array &&
equals$2(a.bytes, data.bytes));
}
}
/**
* Represents a multihash digest which carries information about the
* hashing algorithm and an actual hash digest.
*/
class Digest {
code;
size;
digest;
bytes;
/**
* Creates a multihash digest.
*/
constructor(code, size, digest, bytes) {
this.code = code;
this.size = size;
this.digest = digest;
this.bytes = bytes;
}
}
const code = 0x0;
const name = 'identity';
const encode$1 = coerce;
function digest(input) {
return create(code, encode$1(input));
}
const identity = { code, name, encode: encode$1, digest };
function from({ name, code, encode }) {
return new Hasher(name, code, encode);
}
/**
* Hasher represents a hashing algorithm implementation that produces as
* `MultihashDigest`.
*/
class Hasher {
name;
code;
encode;
constructor(name, code, encode) {
this.name = name;
this.code = code;
this.encode = encode;
}
digest(input) {
if (input instanceof Uint8Array) {
const result = this.encode(input);
return result instanceof Uint8Array
? create(this.code, result)
/* c8 ignore next 1 */
: result.then(digest => create(this.code, digest));
}
else {
throw Error('Unknown type, must be binary type');
/* c8 ignore next 1 */
}
}
}
/* global crypto */
function sha(name) {
return async (data) => new Uint8Array(await crypto.subtle.digest(name, data));
}
const sha256$2 = from({
name: 'sha2-256',
code: 0x12,
encode: sha('SHA-256')
});
function format(link, base) {
const { bytes, version } = link;
switch (version) {
case 0:
return toStringV0(bytes, baseCache(link), base ?? base58btc.encoder);
default:
return toStringV1(bytes, baseCache(link), (base ?? base32.encoder));
}
}
const cache = new WeakMap();
function baseCache(cid) {
const baseCache = cache.get(cid);
if (baseCache == null) {
const baseCache = new Map();
cache.set(cid, baseCache);
return baseCache;
}
return baseCache;
}
class CID {
code;
version;
multihash;
bytes;
'/';
/**
* @param version - Version of the CID
* @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
* @param multihash - (Multi)hash of the of the content.
*/
constructor(version, code, multihash, bytes) {
this.code = code;
this.version = version;
this.multihash = multihash;
this.bytes = bytes;
// flag to serializers that this is a CID and
// should be treated specially
this['/'] = bytes;
}
/**
* Signalling `cid.asCID === cid` has been replaced with `cid['/'] === cid.bytes`
* please either use `CID.asCID(cid)` or switch to new signalling mechanism
*
* @deprecated
*/
get asCID() {
return this;
}
// ArrayBufferView
get byteOffset() {
return this.bytes.byteOffset;
}
// ArrayBufferView
get byteLength() {
return this.bytes.byteLength;
}
toV0() {
switch (this.version) {
case 0: {
return this;
}
case 1: {
const { code, multihash } = this;
if (code !== DAG_PB_CODE) {
throw new Error('Cannot convert a non dag-pb CID to CIDv0');
}
// sha2-256
if (multihash.code !== SHA_256_CODE) {
throw new Error('Cannot convert non sha2-256 multihash CID to CIDv0');
}
return (CID.createV0(multihash));
}
default: {
throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`);
}
}
}
toV1() {
switch (this.version) {
case 0: {
const { code, digest } = this.multihash;
const multihash = create(code, digest);
return (CID.createV1(this.code, multihash));
}
case 1: {
return this;
}
default: {
throw Error(`Can not convert CID version ${this.version} to version 1. This is a bug please report`);
}
}
}
equals(other) {
return CID.equals(this, other);
}
static equals(self, other) {
const unknown = other;
return (unknown != null &&
self.code === unknown.code &&
self.version === unknown.version &&
equals$1(self.multihash, unknown.multihash));
}
toString(base) {
return format(this, base);
}
toJSON() {
return { '/': format(this) };
}
link() {
return this;
}
[Symbol.toStringTag] = 'CID';
// Legacy
[Symbol.for('nodejs.util.inspect.custom')]() {
return `CID(${this.toString()})`;
}
/**
* Takes any input `value` and returns a `CID` instance if it was
* a `CID` otherwise returns `null`. If `value` is instanceof `CID`
* it will return value back. If `value` is not instance of this CID
* class, but is compatible CID it will return new instance of this
* `CID` class. Otherwise returns null.
*
* This allows two different incompatible versions of CID library to
* co-exist and interop as long as binary interface is compatible.
*/
static asCID(input) {
if (input == null) {
return null;
}
const value = input;
if (value instanceof CID) {
// If value is instance of CID then we're all set.
return value;
}
else if ((value['/'] != null && value['/'] === value.bytes) || value.asCID === value) {
// If value isn't instance of this CID class but `this.asCID === this` or
// `value['/'] === value.bytes` is true it is CID instance coming from a
// different implementation (diff version or duplicate). In that case we
// rebase it to this `CID` implementation so caller is guaranteed to get
// instance with expected API.
const { version, code, multihash, bytes } = value;
return new CID(version, code, multihash, bytes ?? encodeCID(version, code, multihash.bytes));
}
else if (value[cidSymbol] === true) {
// If value is a CID from older implementation that used to be tagged via
// symbol we still rebase it to the this `CID` implementation by
// delegating that to a constructor.
const { version, multihash, code } = value;
const digest = decode$2(multihash);
return CID.create(version, code, digest);
}
else {
// Otherwise value is not a CID (or an incompatible version of it) in
// which case we return `null`.
return null;
}
}
/**
* @param version - Version of the CID
* @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
* @param digest - (Multi)hash of the of the content.
*/
static create(version, code, digest) {
if (typeof code !== 'number') {
throw new Error('String codecs are no longer supported');
}
if (!(digest.bytes instanceof Uint8Array)) {
throw new Error('Invalid digest');
}
switch (version) {
case 0: {
if (code !== DAG_PB_CODE) {
throw new Error(`Version 0 CID must use dag-pb (code: ${DAG_PB_CODE}) block encoding`);
}
else {
return new CID(version, code, digest, digest.bytes);
}
}
case 1: {
const bytes = encodeCID(version, code, digest.bytes);
return new CID(version, code, digest, bytes);
}
default: {
throw new Error('Invalid version');
}
}
}
/**
* Simplified version of `create` for CIDv0.
*/
static createV0(digest) {
return CID.create(0, DAG_PB_CODE, digest);
}
/**
* Simplified version of `create` for CIDv1.
*
* @param code - Content encoding format code.
* @param digest - Multihash of the content.
*/
static createV1(code, digest) {
return CID.create(1, code, digest);
}
/**
* Decoded a CID from its binary representation. The byte array must contain
* only the CID with no additional bytes.
*
* An error will be thrown if the bytes provided do not contain a valid
* binary representation of a CID.
*/
static decode(bytes) {
const [cid, remainder] = CID.decodeFirst(bytes);
if (remainder.length !== 0) {
throw new Error('Incorrect length');
}
return cid;
}
/**
* Decoded a CID from its binary representation at the beginning of a byte
* array.
*
* Returns an array with the first element containing the CID and the second
* element containing the remainder of the original byte array. The remainder
* will be a zero-length byte array if the provided bytes only contained a
* binary CID representation.
*/
static decodeFirst(bytes) {
const specs = CID.inspectBytes(bytes);
const prefixSize = specs.size - specs.multihashSize;
const multihashBytes = coerce(bytes.subarray(prefixSize, prefixSize + specs.multihashSize));
if (multihashBytes.byteLength !== specs.multihashSize) {
throw new Error('Incorrect length');
}
const digestBytes = multihashBytes.subarray(specs.multihashSize - specs.digestSize);
const digest = new Digest(specs.multihashCode, specs.digestSize, digestBytes, multihashBytes);
const cid = specs.version === 0
? CID.createV0(digest)
: CID.createV1(specs.codec, digest);
return [cid, bytes.subarray(specs.size)];
}
/**
* Inspect the initial bytes of a CID to determine its properties.
*
* Involves decoding up to 4 varints. Typically this will require only 4 to 6
* bytes but for larger multicodec code values and larger multihash digest
* lengths these varints can be quite large. It is recommended that at least
* 10 bytes be made available in the `initialBytes` argument for a complete
* inspection.
*/
static inspectBytes(initialBytes) {
let offset = 0;
const next = () => {
const [i, length] = decode$3(initialBytes.subarray(offset));
offset += length;
return i;
};
let version = next();
let codec = DAG_PB_CODE;
if (version === 18) {
// CIDv0
version = 0;
offset = 0;
}
else {
codec = next();
}
if (version !== 0 && version !== 1) {
throw new RangeError(`Invalid CID version ${version}`);
}
const prefixSize = offset;
const multihashCode = next(); // multihash code
const digestSize = next(); // multihash length
const size = offset + digestSize;
const multihashSize = size - prefixSize;
return { version, codec, multihashCode, digestSize, multihashSize, size };
}
/**
* Takes cid in a string representation and creates an instance. If `base`
* decoder is not provided will use a default from the configuration. It will
* throw an error if encoding of the CID is not compatible with supplied (or
* a default decoder).
*/
static parse(source, base) {
const [prefix, bytes] = parseCIDtoBytes(source, base);
const cid = CID.decode(bytes);
if (cid.version === 0 && source[0] !== 'Q') {
throw Error('Version 0 CID string must not include multibase prefix');
}
// Cache string representation to avoid computing it on `this.toString()`
baseCache(cid).set(prefix, source);
return cid;
}
}
function parseCIDtoBytes(source, base) {
switch (source[0]) {
// CIDv0 is parsed differently
case 'Q': {
const decoder = base ?? base58btc;
return [
base58btc.prefix,
decoder.decode(`${base58btc.prefix}${source}`)
];
}
case base58btc.prefix: {
const decoder = base ?? base58btc;
return [base58btc.prefix, decoder.decode(source)];
}
case base32.prefix: {
const decoder = base ?? base32;
return [base32.prefix, decoder.decode(source)];
}
case base36.prefix: {
const decoder = base ?? base36;
return [base36.prefix, decoder.decode(source)];
}
default: {
if (base == null) {
throw Error('To parse non base32, base36 or base58btc encoded CID multibase decoder must be provided');
}
return [source[0], base.decode(source)];
}
}
}
function toStringV0(bytes, cache, base) {
const { prefix } = base;
if (prefix !== base58btc.prefix) {
throw Error(`Cannot string encode V0 in ${base.name} encoding`);
}
const cid = cache.get(prefix);
if (cid == null) {
const cid = base.encode(bytes).slice(1);
cache.set(prefix, cid);
return cid;
}
else {
return cid;
}
}
function toStringV1(bytes, cache, base) {
const { prefix } = base;
const cid = cache.get(prefix);
if (cid == null) {
const cid = base.encode(bytes);
cache.set(prefix, cid);
return cid;
}
else {
return cid;
}
}
const DAG_PB_CODE = 0x70;
const SHA_256_CODE = 0x12;
function encodeCID(version, code, multihash) {
const codeOffset = encodingLength$1(version);
const hashOffset = codeOffset + encodingLength$1(code);
const bytes = new Uint8Array(hashOffset + multihash.byteLength);
encodeTo(version, bytes, 0);
encodeTo(code, bytes, codeOffset);
bytes.set(multihash, hashOffset);
return bytes;
}
const cidSymbol = Symbol.for('@ipld/js-cid/CID');
const bases = { ...identityBase, ...base2$1, ...base8$1, ...base10$1, ...base16$1, ...base32$1, ...base36$1, ...base58, ...base64$1, ...base256emoji$1 };
/**
* Returns a `Uint8Array` of the requested size. Referenced memory will
* be initialized to 0.
*/
function alloc$1(size = 0) {
return new Uint8Array(size);
}
/**
* Where possible returns a Uint8Array of the requested size that references
* uninitialized memory. Only use if you are certain you will immediately
* overwrite every value in the returned `Uint8Array`.
*/
function allocUnsafe(size = 0) {
return new Uint8Array(size);
}
function createCodec$1(name, prefix, encode, decode) {
return {
name,
prefix,
encoder: {
name,
prefix,
encode
},
decoder: {
decode
}
};
}
const string = createCodec$1('utf8', 'u', (buf) => {
const decoder = new TextDecoder('utf8');
return 'u' + decoder.decode(buf);
}, (str) => {
const encoder = new TextEncoder();
return encoder.encode(str.substring(1));
});
const ascii = createCodec$1('ascii', 'a', (buf) => {
let string = 'a';
for (let i = 0; i < buf.length; i++) {
string += String.fromCharCode(buf[i]);
}
return string;
}, (str) => {
str = str.substring(1);
const buf = allocUnsafe(str.length);
for (let i = 0; i < str.length; i++) {
buf[i] = str.charCodeAt(i);
}
return buf;
});
const BASES = {
utf8: string,
'utf-8': string,
hex: bases.base16,
latin1: ascii,
ascii,
binary: ascii,
...bases
};
/**
* Create a `Uint8Array` from the passed string
*
* Supports `utf8`, `utf-8`, `hex`, and any encoding supported by the multiformats module.
*
* Also `ascii` which is similar to node's 'binary' encoding.
*/
function fromString(string, encoding = 'utf8') {
const base = BASES[encoding];
if (base == null) {
throw new Error(`Unsupported encoding "${encoding}"`);
}
// add multibase prefix
return base.decoder.decode(`${base.prefix}${string}`); // eslint-disable-line @typescript-eslint/restrict-template-expressions
}
/**
* Turns a `Uint8Array` into a string.
*
* Supports `utf8`, `utf-8` and any encoding supported by the multibase module.
*
* Also `ascii` which is similar to node's 'binary' encoding.
*/
function toString(array, encoding = 'utf8') {
const base = BASES[encoding];
if (base == null) {
throw new Error(`Unsupported encoding "${encoding}"`);
}
// strip multibase prefix
return base.encoder.encode(array).substring(1);
}
/**
* Convert input to a byte array.
*
* Handles both `0x` prefixed and non-prefixed strings.
*/
function hexToBytes$2(hex) {
if (typeof hex === "string") {
const _hex = hex.replace(/^0x/i, "");
return fromString(_hex.toLowerCase(), "base16");
}
return hex;
}
/**
* Convert byte array to hex string (no `0x` prefix).
*/
const bytesToHex$2 = (bytes) => toString(bytes, "base16");
/**
* Decode byte array to utf-8 string.
*/
const bytesToUtf8 = (b) => toString(b, "utf8");
/**
* Encode utf-8 string to byte array.
*/
const utf8ToBytes$1 = (s) => fromString(s, "utf8");
/**
* Concatenate using Uint8Arrays as `Buffer` has a different behavior with `DataView`
*/
function concat$1(byteArrays, totalLength) {
const len = totalLength ?? byteArrays.reduce((acc, curr) => acc + curr.length, 0);
const res = new Uint8Array(len);
let offset = 0;
for (const bytes of byteArrays) {
res.set(bytes, offset);
offset += bytes.length;
}
return res;
}
var _nodeResolve_empty = {};
var nodeCrypto = /*#__PURE__*/Object.freeze({
__proto__: null,
default: _nodeResolve_empty
});
/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */
const _0n$5 = BigInt(0);
const _1n$7 = BigInt(1);
const _2n$5 = BigInt(2);
const _3n$2 = BigInt(3);
const _8n$3 = BigInt(8);
const CURVE = Object.freeze({
a: _0n$5,
b: BigInt(7),
P: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'),
h: _1n$7,
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
});
const divNearest$1 = (a, b) => (a + b / _2n$5) / b;
const endo = {
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
splitScalar(k) {
const { n } = CURVE;
const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
const b1 = -_1n$7 * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
const b2 = a1;
const POW_2_128 = BigInt('0x100000000000000000000000000000000');
const c1 = divNearest$1(b2 * k, n);
const c2 = divNearest$1(-b1 * k, n);
let k1 = mod$1(k - c1 * a1 - c2 * a2, n);
let k2 = mod$1(-c1 * b1 - c2 * b2, n);
const k1neg = k1 > POW_2_128;
const k2neg = k2 > POW_2_128;
if (k1neg)
k1 = n - k1;
if (k2neg)
k2 = n - k2;
if (k1 > POW_2_128 || k2 > POW_2_128) {
throw new Error('splitScalarEndo: Endomorphism failed, k=' + k);
}
return { k1neg, k1, k2neg, k2 };
},
};
const fieldLen = 32;
const groupLen = 32;
const hashLen = 32;
const compressedLen = fieldLen + 1;
const uncompressedLen = 2 * fieldLen + 1;
function weierstrass$1(x) {
const { a, b } = CURVE;
const x2 = mod$1(x * x);
const x3 = mod$1(x2 * x);
return mod$1(x3 + a * x + b);
}
const USE_ENDOMORPHISM = CURVE.a === _0n$5;
class ShaError extends Error {
constructor(message) {
super(message);
}
}
function assertJacPoint(other) {
if (!(other instanceof JacobianPoint))
throw new TypeError('JacobianPoint expected');
}
class JacobianPoint {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
static fromAffine(p) {
if (!(p instanceof Point)) {
throw new TypeError('JacobianPoint#fromAffine: expected Point');
}
if (p.equals(Point.ZERO))
return JacobianPoint.ZERO;
return new JacobianPoint(p.x, p.y, _1n$7);
}
static toAffineBatch(points) {
const toInv = invertBatch(points.map((p) => p.z));
return points.map((p, i) => p.toAffine(toInv[i]));
}
static normalizeZ(points) {
return JacobianPoint.toAffineBatch(points).map(JacobianPoint.fromAffine);
}
equals(other) {
assertJacPoint(other);
const { x: X1, y: Y1, z: Z1 } = this;
const { x: X2, y: Y2, z: Z2 } = other;
const Z1Z1 = mod$1(Z1 * Z1);
const Z2Z2 = mod$1(Z2 * Z2);
const U1 = mod$1(X1 * Z2Z2);
const U2 = mod$1(X2 * Z1Z1);
const S1 = mod$1(mod$1(Y1 * Z2) * Z2Z2);
const S2 = mod$1(mod$1(Y2 * Z1) * Z1Z1);
return U1 === U2 && S1 === S2;
}
negate() {
return new JacobianPoint(this.x, mod$1(-this.y), this.z);
}
double() {
const { x: X1, y: Y1, z: Z1 } = this;
const A = mod$1(X1 * X1);
const B = mod$1(Y1 * Y1);
const C = mod$1(B * B);
const x1b = X1 + B;
const D = mod$1(_2n$5 * (mod$1(x1b * x1b) - A - C));
const E = mod$1(_3n$2 * A);
const F = mod$1(E * E);
const X3 = mod$1(F - _2n$5 * D);
const Y3 = mod$1(E * (D - X3) - _8n$3 * C);
const Z3 = mod$1(_2n$5 * Y1 * Z1);
return new JacobianPoint(X3, Y3, Z3);
}
add(other) {
assertJacPoint(other);
const { x: X1, y: Y1, z: Z1 } = this;
const { x: X2, y: Y2, z: Z2 } = other;
if (X2 === _0n$5 || Y2 === _0n$5)
return this;
if (X1 === _0n$5 || Y1 === _0n$5)
return other;
const Z1Z1 = mod$1(Z1 * Z1);
const Z2Z2 = mod$1(Z2 * Z2);
const U1 = mod$1(X1 * Z2Z2);
const U2 = mod$1(X2 * Z1Z1);
const S1 = mod$1(mod$1(Y1 * Z2) * Z2Z2);
const S2 = mod$1(mod$1(Y2 * Z1) * Z1Z1);
const H = mod$1(U2 - U1);
const r = mod$1(S2 - S1);
if (H === _0n$5) {
if (r === _0n$5) {
return this.double();
}
else {
return JacobianPoint.ZERO;
}
}
const HH = mod$1(H * H);
const HHH = mod$1(H * HH);
const V = mod$1(U1 * HH);
const X3 = mod$1(r * r - HHH - _2n$5 * V);
const Y3 = mod$1(r * (V - X3) - S1 * HHH);
const Z3 = mod$1(Z1 * Z2 * H);
return new JacobianPoint(X3, Y3, Z3);
}
subtract(other) {
return this.add(other.negate());
}
multiplyUnsafe(scalar) {
const P0 = JacobianPoint.ZERO;
if (typeof scalar === 'bigint' && scalar === _0n$5)
return P0;
let n = normalizeScalar(scalar);
if (n === _1n$7)
return this;
if (!USE_ENDOMORPHISM) {
let p = P0;
let d = this;
while (n > _0n$5) {
if (n & _1n$7)
p = p.add(d);
d = d.double();
n >>= _1n$7;
}
return p;
}
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
let k1p = P0;
let k2p = P0;
let d = this;
while (k1 > _0n$5 || k2 > _0n$5) {
if (k1 & _1n$7)
k1p = k1p.add(d);
if (k2 & _1n$7)
k2p = k2p.add(d);
d = d.double();
k1 >>= _1n$7;
k2 >>= _1n$7;
}
if (k1neg)
k1p = k1p.negate();
if (k2neg)
k2p = k2p.negate();
k2p = new JacobianPoint(mod$1(k2p.x * endo.beta), k2p.y, k2p.z);
return k1p.add(k2p);
}
precomputeWindow(W) {
const windows = USE_ENDOMORPHISM ? 128 / W + 1 : 256 / W + 1;
const points = [];
let p = this;
let base = p;
for (let window = 0; window < windows; window++) {
base = p;
points.push(base);
for (let i = 1; i < 2 ** (W - 1); i++) {
base = base.add(p);
points.push(base);
}
p = base.double();
}
return points;
}
wNAF(n, affinePoint) {
if (!affinePoint && this.equals(JacobianPoint.BASE))
affinePoint = Point.BASE;
const W = (affinePoint && affinePoint._WINDOW_SIZE) || 1;
if (256 % W) {
throw new Error('Point#wNAF: Invalid precomputation window, must be power of 2');
}
let precomputes = affinePoint && pointPrecomputes$1.get(affinePoint);
if (!precomputes) {
precomputes = this.precomputeWindow(W);
if (affinePoint && W !== 1) {
precomputes = JacobianPoint.normalizeZ(precomputes);
pointPrecomputes$1.set(affinePoint, precomputes);
}
}
let p = JacobianPoint.ZERO;
let f = JacobianPoint.BASE;
const windows = 1 + (USE_ENDOMORPHISM ? 128 / W : 256 / W);
const windowSize = 2 ** (W - 1);
const mask = BigInt(2 ** W - 1);
const maxNumber = 2 ** W;
const shiftBy = BigInt(W);
for (let window = 0; window < windows; window++) {
const offset = window * windowSize;
let wbits = Number(n & mask);
n >>= shiftBy;
if (wbits > windowSize) {
wbits -= maxNumber;
n += _1n$7;
}
const offset1 = offset;
const offset2 = offset + Math.abs(wbits) - 1;
const cond1 = window % 2 !== 0;
const cond2 = wbits < 0;
if (wbits === 0) {
f = f.add(constTimeNegate(cond1, precomputes[offset1]));
}
else {
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
}
}
return { p, f };
}
multiply(scalar, affinePoint) {
let n = normalizeScalar(scalar);
let point;
let fake;
if (USE_ENDOMORPHISM) {
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint);
let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
k1p = constTimeNegate(k1neg, k1p);
k2p = constTimeNegate(k2neg, k2p);
k2p = new JacobianPoint(mod$1(k2p.x * endo.beta), k2p.y, k2p.z);
point = k1p.add(k2p);
fake = f1p.add(f2p);
}
else {
const { p, f } = this.wNAF(n, affinePoint);
point = p;
fake = f;
}
return JacobianPoint.normalizeZ([point, fake])[0];
}
toAffine(invZ) {
const { x, y, z } = this;