@mavrykdynamics/taquito-michel-codec
Version:
Michelson parser/validator/formatter
256 lines (255 loc) • 7.37 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeBase58Check = exports.decodeBase58Check = exports.encodeBase58 = exports.decodeBase58 = exports.Base58DecodingError = void 0;
const taquito_core_1 = require("@mavrykdynamics/taquito-core");
const H = [
0x6a09e667 | 0,
0xbb67ae85 | 0,
0x3c6ef372 | 0,
0xa54ff53a | 0,
0x510e527f | 0,
0x9b05688c | 0,
0x1f83d9ab | 0,
0x5be0cd19 | 0,
];
const K = [
0x428a2f98 | 0,
0x71374491 | 0,
0xb5c0fbcf | 0,
0xe9b5dba5 | 0,
0x3956c25b | 0,
0x59f111f1 | 0,
0x923f82a4 | 0,
0xab1c5ed5 | 0,
0xd807aa98 | 0,
0x12835b01 | 0,
0x243185be | 0,
0x550c7dc3 | 0,
0x72be5d74 | 0,
0x80deb1fe | 0,
0x9bdc06a7 | 0,
0xc19bf174 | 0,
0xe49b69c1 | 0,
0xefbe4786 | 0,
0x0fc19dc6 | 0,
0x240ca1cc | 0,
0x2de92c6f | 0,
0x4a7484aa | 0,
0x5cb0a9dc | 0,
0x76f988da | 0,
0x983e5152 | 0,
0xa831c66d | 0,
0xb00327c8 | 0,
0xbf597fc7 | 0,
0xc6e00bf3 | 0,
0xd5a79147 | 0,
0x06ca6351 | 0,
0x14292967 | 0,
0x27b70a85 | 0,
0x2e1b2138 | 0,
0x4d2c6dfc | 0,
0x53380d13 | 0,
0x650a7354 | 0,
0x766a0abb | 0,
0x81c2c92e | 0,
0x92722c85 | 0,
0xa2bfe8a1 | 0,
0xa81a664b | 0,
0xc24b8b70 | 0,
0xc76c51a3 | 0,
0xd192e819 | 0,
0xd6990624 | 0,
0xf40e3585 | 0,
0x106aa070 | 0,
0x19a4c116 | 0,
0x1e376c08 | 0,
0x2748774c | 0,
0x34b0bcb5 | 0,
0x391c0cb3 | 0,
0x4ed8aa4a | 0,
0x5b9cca4f | 0,
0x682e6ff3 | 0,
0x748f82ee | 0,
0x78a5636f | 0,
0x84c87814 | 0,
0x8cc70208 | 0,
0x90befffa | 0,
0xa4506ceb | 0,
0xbef9a3f7 | 0,
0xc67178f2 | 0,
];
/**
* @category Error
* @description Error that indicates a failure when decoding a base58 encoding
*/
class Base58DecodingError extends taquito_core_1.TaquitoError {
constructor(message) {
super();
this.message = message;
this.name = 'Base58DecodingError';
}
}
exports.Base58DecodingError = Base58DecodingError;
// https://tools.ietf.org/html/rfc6234
function sha256(msg) {
// pad the message
const r = (msg.length + 9) % 64;
const pad = r === 0 ? 0 : 64 - r;
if (msg.length > 268435455) {
throw new taquito_core_1.InvalidMessageError('', `: Invalid length ${msg.length} is too big -- SHA-256.`);
}
const l = msg.length << 3;
const buffer = [
...msg,
0x80,
...new Array(pad).fill(0),
0,
0,
0,
0,
(l >> 24) & 0xff,
(l >> 16) & 0xff,
(l >> 8) & 0xff,
l & 0xff,
];
function ror(x, n) {
return (x >>> n) | (x << (32 - n));
}
const h = [...H];
const w = new Array(64);
const v = new Array(8);
for (let offset = 0; offset < buffer.length; offset += 64) {
let q = offset;
let i = 0;
while (i < 16) {
w[i] = (buffer[q] << 24) | (buffer[q + 1] << 16) | (buffer[q + 2] << 8) | buffer[q + 3];
q += 4;
i++;
}
while (i < 64) {
const s0 = ror(w[i - 15], 7) ^ ror(w[i - 15], 18) ^ (w[i - 15] >>> 3);
const s1 = ror(w[i - 2], 17) ^ ror(w[i - 2], 19) ^ (w[i - 2] >>> 10);
w[i] = ((s1 | 0) + w[i - 7] + s0 + w[i - 16]) | 0;
i++;
}
for (let i = 0; i < 8; i++) {
v[i] = h[i];
}
for (let i = 0; i < 64; i++) {
const b0 = ror(v[0], 2) ^ ror(v[0], 13) ^ ror(v[0], 22);
const b1 = ror(v[4], 6) ^ ror(v[4], 11) ^ ror(v[4], 25);
const t1 = (v[7] + b1 + ((v[4] & v[5]) ^ (~v[4] & v[6])) + K[i] + w[i]) | 0;
const t2 = (b0 + ((v[0] & v[1]) ^ (v[0] & v[2]) ^ (v[1] & v[2]))) | 0;
v[7] = v[6];
v[6] = v[5];
v[5] = v[4];
v[4] = (v[3] + t1) | 0;
v[3] = v[2];
v[2] = v[1];
v[1] = v[0];
v[0] = (t1 + t2) | 0;
}
for (let i = 0; i < 8; i++) {
h[i] = (h[i] + v[i]) | 0;
}
}
const digest = [];
for (const v of h) {
digest.push((v >> 24) & 0xff);
digest.push((v >> 16) & 0xff);
digest.push((v >> 8) & 0xff);
digest.push(v & 0xff);
}
return digest;
}
const base58alphabetFwd = [
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,
];
const base58alphabetBwd = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62, 63, 64, 65, 66,
67, 68, 69, 70, 71, 72, 73,
];
function byteAt(src, i) {
const c = src.charCodeAt(i) - 49;
if (c >= base58alphabetFwd.length || base58alphabetFwd[c] === -1) {
throw new Base58DecodingError(`Unexpected character at position ${i}: ${src[i]}`);
}
return base58alphabetFwd[c];
}
function decodeBase58(src) {
const acc = [];
let i = 0;
// count and skip leading zeros
while (i < src.length && byteAt(src, i) === 0) {
i++;
}
let zeros = i;
while (i < src.length) {
let carry = byteAt(src, i++);
/*
for every symbol x
acc = acc * 58 + x
where acc is a little endian arbitrary length integer
*/
let ii = 0;
while (carry !== 0 || ii < acc.length) {
const m = (acc[ii] || 0) * 58 + carry;
acc[ii++] = m % 256;
carry = Math.floor(m / 256);
}
}
while (zeros-- > 0) {
acc.push(0);
}
return acc.reverse();
}
exports.decodeBase58 = decodeBase58;
function encodeBase58(src) {
const acc = [];
let i = 0;
// count and skip leading zeros
while (i < src.length && src[i] === 0) {
i++;
}
let zeros = i;
while (i < src.length) {
let carry = src[i++];
let ii = 0;
while (carry !== 0 || ii < acc.length) {
const m = (acc[ii] || 0) * 256 + carry;
acc[ii++] = m % 58;
carry = Math.floor(m / 58);
}
}
while (zeros-- > 0) {
acc.push(0);
}
acc.reverse();
return String.fromCharCode(...acc.map((v) => base58alphabetBwd[v] + 49));
}
exports.encodeBase58 = encodeBase58;
function decodeBase58Check(src) {
const buffer = decodeBase58(src);
if (buffer.length < 4) {
throw new Base58DecodingError(`Data is too short ${buffer.length}`);
}
const data = buffer.slice(0, buffer.length - 4);
const sum = buffer.slice(buffer.length - 4);
const computed = sha256(sha256(data));
if (sum[0] !== computed[0] ||
sum[1] !== computed[1] ||
sum[2] !== computed[2] ||
sum[3] !== computed[3]) {
throw new Base58DecodingError('Invalid checksum');
}
return data;
}
exports.decodeBase58Check = decodeBase58Check;
function encodeBase58Check(src) {
const sum = sha256(sha256(src));
return encodeBase58([...src, ...sum.slice(0, 4)]);
}
exports.encodeBase58Check = encodeBase58Check;