UNPKG

3.81 kBJavaScriptView Raw
1// Copyright 2017-2023 @polkadot/util-crypto authors & contributors
2// SPDX-License-Identifier: Apache-2.0
3
4import { _0n, _1n } from '@polkadot/util';
5import { BigInt } from '@polkadot/x-bigint';
6
7// Adapted from https://github.com/pierrec/js-xxhash/blob/0504e76f3d31a21ae8528a7f590c7289c9e431d2/lib/xxhash64.js
8//
9// xxHash64 implementation in pure Javascript
10// Copyright (C) 2016, Pierre Curto
11// MIT license
12//
13// Changes made:
14// - converted to TypeScript
15// - uses native JS BigInt (no external dependencies)
16// - support only for Uint8Array inputs
17// - no constructor function, straight fill & digest
18// - update code removed, only called once, no streams
19
20const P64_1 = BigInt('11400714785074694791');
21const P64_2 = BigInt('14029467366897019727');
22const P64_3 = BigInt('1609587929392839161');
23const P64_4 = BigInt('9650029242287828579');
24const P64_5 = BigInt('2870177450012600261');
25
26// mask for a u64, all bits set
27const U64 = BigInt('0xffffffffffffffff');
28
29// various constants
30const _7n = BigInt(7);
31const _11n = BigInt(11);
32const _12n = BigInt(12);
33const _16n = BigInt(16);
34const _18n = BigInt(18);
35const _23n = BigInt(23);
36const _27n = BigInt(27);
37const _29n = BigInt(29);
38const _31n = BigInt(31);
39const _32n = BigInt(32);
40const _33n = BigInt(33);
41const _64n = BigInt(64);
42const _256n = BigInt(256);
43function rotl(a, b) {
44 const c = a & U64;
45 return (c << b | c >> _64n - b) & U64;
46}
47function fromU8a(u8a, p, count) {
48 const bigints = new Array(count);
49 let offset = 0;
50 for (let i = 0; i < count; i++, offset += 2) {
51 bigints[i] = BigInt(u8a[p + offset] | u8a[p + 1 + offset] << 8);
52 }
53 let result = _0n;
54 for (let i = count - 1; i >= 0; i--) {
55 result = (result << _16n) + bigints[i];
56 }
57 return result;
58}
59function toU8a(h64) {
60 const result = new Uint8Array(8);
61 for (let i = 7; i >= 0; i--) {
62 result[i] = Number(h64 % _256n);
63 h64 = h64 / _256n;
64 }
65 return result;
66}
67function state(initSeed) {
68 const seed = BigInt(initSeed);
69 return {
70 seed,
71 u8a: new Uint8Array(32),
72 u8asize: 0,
73 v1: seed + P64_1 + P64_2,
74 v2: seed + P64_2,
75 v3: seed,
76 v4: seed - P64_1
77 };
78}
79function init(state, input) {
80 if (input.length < 32) {
81 state.u8a.set(input);
82 state.u8asize = input.length;
83 return state;
84 }
85 const limit = input.length - 32;
86 let p = 0;
87 if (limit >= 0) {
88 const adjustV = v => P64_1 * rotl(v + P64_2 * fromU8a(input, p, 4), _31n);
89 do {
90 state.v1 = adjustV(state.v1);
91 p += 8;
92 state.v2 = adjustV(state.v2);
93 p += 8;
94 state.v3 = adjustV(state.v3);
95 p += 8;
96 state.v4 = adjustV(state.v4);
97 p += 8;
98 } while (p <= limit);
99 }
100 if (p < input.length) {
101 state.u8a.set(input.subarray(p, input.length));
102 state.u8asize = input.length - p;
103 }
104 return state;
105}
106export function xxhash64(input, initSeed) {
107 const {
108 seed,
109 u8a,
110 u8asize,
111 v1,
112 v2,
113 v3,
114 v4
115 } = init(state(initSeed), input);
116 let p = 0;
117 let h64 = U64 & BigInt(input.length) + (input.length >= 32 ? ((((rotl(v1, _1n) + rotl(v2, _7n) + rotl(v3, _12n) + rotl(v4, _18n) ^ P64_1 * rotl(v1 * P64_2, _31n)) * P64_1 + P64_4 ^ P64_1 * rotl(v2 * P64_2, _31n)) * P64_1 + P64_4 ^ P64_1 * rotl(v3 * P64_2, _31n)) * P64_1 + P64_4 ^ P64_1 * rotl(v4 * P64_2, _31n)) * P64_1 + P64_4 : seed + P64_5);
118 while (p <= u8asize - 8) {
119 h64 = U64 & P64_4 + P64_1 * rotl(h64 ^ P64_1 * rotl(P64_2 * fromU8a(u8a, p, 4), _31n), _27n);
120 p += 8;
121 }
122 if (p + 4 <= u8asize) {
123 h64 = U64 & P64_3 + P64_2 * rotl(h64 ^ P64_1 * fromU8a(u8a, p, 2), _23n);
124 p += 4;
125 }
126 while (p < u8asize) {
127 h64 = U64 & P64_1 * rotl(h64 ^ P64_5 * BigInt(u8a[p++]), _11n);
128 }
129 h64 = U64 & P64_2 * (h64 ^ h64 >> _33n);
130 h64 = U64 & P64_3 * (h64 ^ h64 >> _29n);
131 return toU8a(U64 & (h64 ^ h64 >> _32n));
132}
\No newline at end of file