@javakha77/circomlibjs-hinkal-fork 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/main.cjs CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  var ffjavascript = require('ffjavascript');
4
4
  var blake1_js = require('@noble/hashes/blake1.js');
5
+ var poseidonLite = require('poseidon-lite');
6
+
7
+ function _interopNamespaceDefault(e) {
8
+ var n = Object.create(null);
9
+ if (e) {
10
+ Object.keys(e).forEach(function (k) {
11
+ if (k !== 'default') {
12
+ var d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: function () { return e[k]; }
16
+ });
17
+ }
18
+ });
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+
24
+ var poseidonLite__namespace = /*#__PURE__*/_interopNamespaceDefault(poseidonLite);
5
25
 
6
26
  async function buildBabyJub() {
7
27
  const bn128 = await ffjavascript.getCurveFromName("bn128", true);
@@ -24948,7 +24968,7 @@ var poseidonConstants = {
24948
24968
  ]
24949
24969
  };
24950
24970
 
24951
- async function buildPoseidon() {
24971
+ async function buildPoseidon$1() {
24952
24972
  const bn128 = await ffjavascript.getCurveFromName("bn128", true, buildPoseidonWasm);
24953
24973
 
24954
24974
  const F = bn128.Fr;
@@ -25379,7 +25399,7 @@ function buildPoseidonWasm(module) {
25379
25399
 
25380
25400
  async function buildEddsa() {
25381
25401
  const babyJub = await buildBabyJub();
25382
- const poseidon = await buildPoseidon();
25402
+ const poseidon = await buildPoseidon$1();
25383
25403
  return new Eddsa(babyJub, poseidon);
25384
25404
  }
25385
25405
 
@@ -25474,7 +25494,270 @@ class Eddsa {
25474
25494
  }
25475
25495
  }
25476
25496
 
25497
+ const CIRCOM_P = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
25498
+
25499
+ // Reduce value into [0, m); handles negative inputs.
25500
+ const mod = (value, m = CIRCOM_P) => {
25501
+ const result = value % m;
25502
+ return result >= 0n ? result : result + m;
25503
+ };
25504
+
25505
+ // Modular inverse via extended Euclidean algorithm (a^-1 mod m).
25506
+ const modInverse = (value, m = CIRCOM_P) => {
25507
+ let lm = 1n;
25508
+ let hm = 0n;
25509
+ let low = mod(value, m);
25510
+ let high = m;
25511
+
25512
+ if (low === 0n) throw new Error('Division by zero');
25513
+
25514
+ while (low > 1n) {
25515
+ const remainder = high % low;
25516
+ const quotient = high / low;
25517
+ high = low;
25518
+ low = remainder;
25519
+ const nm = hm - lm * quotient;
25520
+ hm = lm;
25521
+ lm = nm;
25522
+ }
25523
+
25524
+ return lm < 0n ? lm + m : lm;
25525
+ };
25526
+
25527
+ const P = CIRCOM_P;
25528
+
25529
+ // BabyJub base-field arithmetic over CIRCOM_P (same semantics as circomlibjs F).
25530
+ const F = {
25531
+ p: P,
25532
+ zero: 0n,
25533
+ one: 1n,
25534
+ e: (v) => mod(BigInt(v)),
25535
+ add: (a, b) => mod(a + b),
25536
+ sub: (a, b) => mod(a - b),
25537
+ mul: (a, b) => mod(a * b),
25538
+ div: (a, b) => {
25539
+ if (b === 0n) throw new Error('Division by zero in BabyJub field');
25540
+ return mod(a * modInverse(b));
25541
+ },
25542
+ toString: (a) => mod(a).toString(),
25543
+ };
25544
+
25545
+ /**
25546
+ * @typedef {{ X: bigint, Y: bigint, Z: bigint, T: bigint }} ExtPoint
25547
+ */
25548
+
25549
+ // Neutral element in extended coordinates (affine identity 0, 1).
25550
+ const IDENTITY = { X: F.zero, Y: F.one, Z: F.one, T: F.zero };
25551
+
25552
+ // Embed an affine (x, y) point into extended twisted Edwards form.
25553
+ const toExtended = (affine) => {
25554
+ const x = F.e(affine[0]);
25555
+ const y = F.e(affine[1]);
25556
+ return { X: x, Y: y, Z: F.one, T: F.mul(x, y) };
25557
+ };
25558
+
25559
+ // Project an extended point back to affine (x, y) coordinates.
25560
+ const toAffine = (point) => {
25561
+ const zInv = modInverse(point.Z);
25562
+ return [F.mul(point.X, zInv), F.mul(point.Y, zInv)];
25563
+ };
25564
+
25565
+ const A = F.e('168700');
25566
+ const D = F.e('168696');
25567
+
25568
+ // Add two extended points (add-2008-hwcd; no per-step field inversions).
25569
+ const addExtended = (p1, p2) => {
25570
+ const a = F.mul(p1.X, p2.X);
25571
+ const b = F.mul(p1.Y, p2.Y);
25572
+ const c = F.mul(F.mul(p1.T, p2.T), D);
25573
+ const d = F.mul(p1.Z, p2.Z);
25574
+ const e = F.sub(F.mul(F.add(p1.X, p1.Y), F.add(p2.X, p2.Y)), F.add(a, b));
25575
+ const f = F.sub(d, c);
25576
+ const g = F.add(d, c);
25577
+ const h = F.sub(b, F.mul(A, a));
25578
+ return {
25579
+ X: F.mul(e, f),
25580
+ Y: F.mul(g, h),
25581
+ T: F.mul(e, h),
25582
+ Z: F.mul(f, g),
25583
+ };
25584
+ };
25585
+
25586
+ // Double an extended point (dbl-2008-hwcd; no per-step field inversions).
25587
+ const doubleExtended = (p) => {
25588
+ const a = F.mul(p.X, p.X);
25589
+ const b = F.mul(p.Y, p.Y);
25590
+ const c = F.mul(F.mul(p.Z, p.Z), 2n);
25591
+ const d = F.mul(A, a);
25592
+ const e = F.sub(F.mul(F.add(p.X, p.Y), F.add(p.X, p.Y)), F.add(a, b));
25593
+ const g = F.add(d, b);
25594
+ const f = F.sub(g, c);
25595
+ const h = F.sub(d, b);
25596
+ return {
25597
+ X: F.mul(e, f),
25598
+ Y: F.mul(g, h),
25599
+ T: F.mul(e, h),
25600
+ Z: F.mul(f, g),
25601
+ };
25602
+ };
25603
+
25604
+ // Pure-JS BabyJub curve used on React Native (circomlibjs uses WASM instead).
25605
+ class BabyJubRN {
25606
+ static A = A;
25607
+
25608
+ static D = D;
25609
+
25610
+ F = F;
25611
+
25612
+ A = A;
25613
+
25614
+ D = D;
25615
+
25616
+ // Standard BabyJub generator used by EdDSA (matches circomlibjs Base8).
25617
+ Base8 = [
25618
+ F.e('5299619240641551281634865583518297030282874472190772894086521144482721001553'),
25619
+ F.e('16950150798460657717958625567821834550301663161624707787222815936182638968203'),
25620
+ ];
25621
+
25622
+ // Add two affine curve points.
25623
+ addPoint(a, b) {
25624
+ return toAffine(addExtended(toExtended(a), toExtended(b)));
25625
+ }
25626
+
25627
+ // Scalar multiplication: returns e * base (double-and-add in extended coords).
25628
+ mulPointEscalar(base, e) {
25629
+ let res = IDENTITY;
25630
+ let exp = toExtended(base);
25631
+ let rem = BigInt(e);
25632
+
25633
+ while (rem !== 0n) {
25634
+ if (rem % 2n === 1n) res = addExtended(res, exp);
25635
+ exp = doubleExtended(exp);
25636
+ rem /= 2n;
25637
+ }
25638
+
25639
+ return toAffine(res);
25640
+ }
25641
+ }
25642
+
25643
+ const toBigInt = (v) => {
25644
+ switch (typeof v) {
25645
+ case 'bigint': return v;
25646
+ case 'boolean': return v ? 1n : 0n;
25647
+ case 'number':
25648
+ if (!Number.isInteger(v)) throw new TypeError(`Poseidon: non-integer Number ${v}`);
25649
+ return BigInt(v);
25650
+ case 'string': {
25651
+ try { return BigInt(v.trim()); }
25652
+ catch { throw new TypeError(`Poseidon: cannot parse string "${v}" as an integer`); }
25653
+ }
25654
+ default:
25655
+ throw new TypeError(`Poseidon.F: unsupported value of type ${typeof v}`);
25656
+ }
25657
+ };
25658
+
25659
+ // poseidon-lite exposes `poseidon1`..`poseidon16`; wrap them in a `buildPoseidon`-shaped
25660
+ // factory (matching the WASM reference) so callers — and the existing
25661
+ // `poseidon.F.toString(...)` pattern — keep working on RN.
25662
+ const buildPoseidon = () => {
25663
+ const poseidon = (inputs, initState = 0, nOut = 1) => {
25664
+ const fn = poseidonLite__namespace[`poseidon${inputs.length}`];
25665
+ if (!fn) throw new Error(`Poseidon: arity ${inputs.length} not supported (1..16)`);
25666
+ const formattedInputs = inputs.map((v) => toBigInt(v));
25667
+
25668
+ if (nOut > 1) {
25669
+ const results = fn(formattedInputs, nOut);
25670
+ return results.map(v => BigInt(v));
25671
+ }
25672
+
25673
+ const res = fn(formattedInputs);
25674
+ return BigInt(res);
25675
+ };
25676
+ poseidon.F = {
25677
+ toString: (v) => toBigInt(v).toString(),
25678
+ e: (v) => toBigInt(v),
25679
+ eq: (a, b) => toBigInt(a) === toBigInt(b),
25680
+ };
25681
+ return poseidon;
25682
+ };
25683
+
25684
+ /* eslint-disable no-bitwise */
25685
+ // React Native port of circomlibjs-hinkal-fork/src/eddsa.js (Poseidon EdDSA over BabyJubJub).
25686
+
25687
+ const BABYJUB_ORDER = 21888242871839275222246405745257275088614511777268538073601725287587578984328n;
25688
+ const SUB_ORDER = BABYJUB_ORDER / 8n;
25689
+
25690
+ const leBuff2int = (buff, offset = 0, length = buff.length - offset) => {
25691
+ let result = 0n;
25692
+ for (let i = length - 1; i >= 0; i -= 1) {
25693
+ result = (result << 8n) + BigInt(buff[offset + i]);
25694
+ }
25695
+ return result;
25696
+ };
25697
+
25698
+ const toRprLE = (buff, offset, value, length) => {
25699
+ let v = mod(value);
25700
+ for (let i = 0; i < length; i += 1) {
25701
+ buff[offset + i] = Number(v & 0xffn);
25702
+ v >>= 8n;
25703
+ }
25704
+ };
25705
+
25706
+ const modSubOrder = (value) => mod(value, SUB_ORDER);
25707
+
25708
+ const pruneBuffer = (buff) => {
25709
+ const out = new Uint8Array(buff);
25710
+ out[0] = out[0] & 0xf8;
25711
+ out[31] = out[31] & 0x7f;
25712
+ out[31] = out[31] | 0x40;
25713
+ return out;
25714
+ };
25715
+
25716
+ /**
25717
+ * @typedef {((inputs: bigint[]) => bigint) & { F: { toString: (v: bigint | number | string) => string } }} PoseidonFn
25718
+ */
25719
+
25720
+ class EddsaRN {
25721
+ constructor(babyJub, poseidon) {
25722
+ this.babyJub = babyJub;
25723
+ this.poseidon = poseidon;
25724
+ }
25725
+
25726
+ prv2pub(prv) {
25727
+ const sBuff = pruneBuffer(blake1_js.blake512(prv).slice(0, 32));
25728
+ const s = leBuff2int(sBuff, 0, 32);
25729
+ return this.babyJub.mulPointEscalar(this.babyJub.Base8, s / 8n);
25730
+ }
25731
+
25732
+ signPoseidon(prv, msg) {
25733
+ const sBuff = pruneBuffer(blake1_js.blake512(prv));
25734
+ const s = leBuff2int(sBuff, 0, 32);
25735
+ const A = this.babyJub.mulPointEscalar(this.babyJub.Base8, s / 8n);
25736
+
25737
+ const composeBuff = new Uint8Array(64);
25738
+ composeBuff.set(sBuff.slice(32), 0);
25739
+ toRprLE(composeBuff, 32, msg, 32);
25740
+
25741
+ const rBuff = blake1_js.blake512(composeBuff);
25742
+ const r = modSubOrder(leBuff2int(rBuff, 0, 64));
25743
+ const R8 = this.babyJub.mulPointEscalar(this.babyJub.Base8, r);
25744
+
25745
+ const hm = this.poseidon([R8[0], R8[1], A[0], A[1], msg]);
25746
+ const hms = mod(BigInt(this.poseidon.F.toString(hm)));
25747
+ const S = modSubOrder(r + modSubOrder(hms * s));
25748
+
25749
+ return { R8, S };
25750
+ }
25751
+ }
25752
+
25753
+ const buildEddsaRN = async () => {
25754
+ return new EddsaRN(new BabyJubRN(), buildPoseidon());
25755
+ };
25756
+
25757
+ exports.BabyJubRN = BabyJubRN;
25477
25758
  exports.buildBabyjub = buildBabyJub;
25478
25759
  exports.buildEddsa = buildEddsa;
25479
- exports.buildPoseidon = buildPoseidon;
25760
+ exports.buildEddsaRN = buildEddsaRN;
25761
+ exports.buildPoseidon = buildPoseidon$1;
25762
+ exports.buildPoseidonRN = buildPoseidon;
25480
25763
  exports.buildPoseidonWasm = buildPoseidonWasm;
package/main.js CHANGED
@@ -8,4 +8,4 @@ export { buildEddsaRN } from "./src/EddsaRN.js";
8
8
 
9
9
  export { BabyJubRN } from "./src/babyjubRN.js";
10
10
 
11
- export { PoseidonRN } from "./src/poseidonRN.js";
11
+ export { buildPoseidon as buildPoseidonRN } from "./src/poseidonRN.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@javakha77/circomlibjs-hinkal-fork",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Javascript library to work with circomlib",
5
5
  "keywords": [
6
6
  "circom",
package/src/EddsaRN.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // React Native port of circomlibjs-hinkal-fork/src/eddsa.js (Poseidon EdDSA over BabyJubJub).
3
3
  import { blake512 } from '@noble/hashes/blake1.js';
4
4
  import { BabyJubRN } from './babyjubRN.js';
5
- import { PoseidonRN } from './poseidonRN.js';
5
+ import { buildPoseidon as buildPoseidonRN } from './poseidonRN.js';
6
6
  import { mod } from './bigint-math.utils.js';
7
7
 
8
8
  const BABYJUB_ORDER = 21888242871839275222246405745257275088614511777268538073601725287587578984328n;
@@ -72,6 +72,5 @@ export class EddsaRN {
72
72
  }
73
73
 
74
74
  export const buildEddsaRN = async () => {
75
- await PoseidonRN.init();
76
- return new EddsaRN(new BabyJubRN(), PoseidonRN.getPoseidon());
75
+ return new EddsaRN(new BabyJubRN(), buildPoseidonRN());
77
76
  };
package/src/poseidonRN.js CHANGED
@@ -1,6 +1,20 @@
1
- import { ethers } from 'ethers';
2
1
  import * as poseidonLite from 'poseidon-lite';
3
- import { toBigInt } from './amounts.utils.js';
2
+
3
+ const toBigInt = (v) => {
4
+ switch (typeof v) {
5
+ case 'bigint': return v;
6
+ case 'boolean': return v ? 1n : 0n;
7
+ case 'number':
8
+ if (!Number.isInteger(v)) throw new TypeError(`Poseidon: non-integer Number ${v}`);
9
+ return BigInt(v);
10
+ case 'string': {
11
+ try { return BigInt(v.trim()); }
12
+ catch { throw new TypeError(`Poseidon: cannot parse string "${v}" as an integer`); }
13
+ }
14
+ default:
15
+ throw new TypeError(`Poseidon.F: unsupported value of type ${typeof v}`);
16
+ }
17
+ };
4
18
 
5
19
  // poseidon-lite exposes `poseidon1`..`poseidon16`; wrap them in a `buildPoseidon`-shaped
6
20
  // factory (matching the WASM reference) so callers — and the existing
@@ -9,7 +23,7 @@ export const buildPoseidon = () => {
9
23
  const poseidon = (inputs, initState = 0, nOut = 1) => {
10
24
  const fn = poseidonLite[`poseidon${inputs.length}`];
11
25
  if (!fn) throw new Error(`Poseidon: arity ${inputs.length} not supported (1..16)`);
12
- const formattedInputs = inputs.map((v) => BigInt(v));
26
+ const formattedInputs = inputs.map((v) => toBigInt(v));
13
27
 
14
28
  if (nOut > 1) {
15
29
  const results = fn(formattedInputs, nOut);
@@ -19,45 +33,10 @@ export const buildPoseidon = () => {
19
33
  const res = fn(formattedInputs);
20
34
  return BigInt(res);
21
35
  };
22
-
23
- poseidon.F = { toString: (v) => BigInt(v).toString(),
24
- e: (v) => BigInt(v),
25
- eq: (a, b) => BigInt(a) === BigInt(b)
26
- };
36
+ poseidon.F = {
37
+ toString: (v) => toBigInt(v).toString(),
38
+ e: (v) => toBigInt(v),
39
+ eq: (a, b) => toBigInt(a) === toBigInt(b),
40
+ };
27
41
  return poseidon;
28
- };
29
-
30
- class PoseidonHolder {
31
- poseidon = undefined;
32
-
33
- async init() {
34
- if (this.poseidon) return;
35
- this.poseidon = buildPoseidon();
36
- return this.poseidon;
37
- }
38
-
39
- getPoseidon() {
40
- return this.poseidon;
41
- }
42
- }
43
-
44
- export const PoseidonRN = new PoseidonHolder();
45
-
46
- export function poseidonFunction(...args) {
47
- const poseidon = PoseidonRN.getPoseidon();
48
- return toBigInt(poseidon.F.toString(poseidon(args)));
49
- }
50
-
51
- /**
52
- * hashing algorithm implementation
53
- * @param args rest parameter to take unlimited number of arguments
54
- * @returns poseidon hash in base 16
55
- */
56
- export const poseidonHash = (...args) => {
57
- const poseidon = PoseidonRN.getPoseidon();
58
- return ethers.toBeHex(poseidon.F.toString(poseidon([...args])));
59
- };
60
-
61
- /**
62
- * @typedef {(...args: unknown[]) => string} PoseidonHasher
63
- */
42
+ };
@@ -1,3 +1 @@
1
- export const CIRCOM_P = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
2
- export const CIRCOM_P_HALF = CIRCOM_P / 2n;
3
- export const CIRCOM_MERKLE_LENGTH = 25;
1
+ export const CIRCOM_P = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
@@ -3,12 +3,12 @@
3
3
  */
4
4
 
5
5
  // Safe JSON.stringify wrapper. Converts BigInt -> string so JSON serialization never throws.
6
- export const safeJsonStringify = (value, replacer = null, space) =>
6
+ export const safeJsonStringify = (value, replacer = null, space) =>
7
7
  JSON.stringify(
8
- value,
9
- (key, nestedValue) => {
8
+ value,
9
+ (key, nestedValue) => {
10
10
  const next = typeof replacer === 'function' ? replacer(key, nestedValue) : nestedValue;
11
11
  return typeof next === 'bigint' ? next.toString() : next;
12
- },
13
- space,
12
+ },
13
+ space,
14
14
  );