circomlibjs-hinkal-fork 0.0.9 → 0.0.11

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.
Binary file
package/.yarnrc.yml ADDED
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
package/build/main.cjs CHANGED
@@ -1,7 +1,27 @@
1
1
  'use strict';
2
2
 
3
3
  var ffjavascript = require('ffjavascript');
4
- var createBlakeHash = require('blake-hash');
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
 
@@ -25398,9 +25418,7 @@ class Eddsa {
25398
25418
  }
25399
25419
 
25400
25420
  prv2pub(prv) {
25401
- const sBuff = this.pruneBuffer(
25402
- createBlakeHash("blake512").update(prv).digest().slice(0, 32),
25403
- );
25421
+ const sBuff = this.pruneBuffer(blake1_js.blake512(prv).slice(0, 32));
25404
25422
  let s = ffjavascript.utils.leBuff2int(sBuff);
25405
25423
  const A = this.babyJub.mulPointEscalar(
25406
25424
  this.babyJub.Base8,
@@ -25411,9 +25429,7 @@ class Eddsa {
25411
25429
 
25412
25430
  signPoseidon(prv, msg) {
25413
25431
  const F = this.babyJub.F;
25414
- const sBuff = this.pruneBuffer(
25415
- createBlakeHash("blake512").update(Buffer.from(prv)).digest(),
25416
- );
25432
+ const sBuff = this.pruneBuffer(blake1_js.blake512(prv));
25417
25433
  const s = ffjavascript.Scalar.fromRprLE(sBuff, 0, 32);
25418
25434
  const A = this.babyJub.mulPointEscalar(
25419
25435
  this.babyJub.Base8,
@@ -25423,9 +25439,7 @@ class Eddsa {
25423
25439
  const composeBuff = new Uint8Array(32 + msg.length);
25424
25440
  composeBuff.set(sBuff.slice(32), 0);
25425
25441
  F.toRprLE(composeBuff, 32, msg);
25426
- const rBuff = createBlakeHash("blake512")
25427
- .update(Buffer.from(composeBuff))
25428
- .digest();
25442
+ const rBuff = blake1_js.blake512(composeBuff);
25429
25443
  let r = ffjavascript.Scalar.mod(ffjavascript.Scalar.fromRprLE(rBuff, 0, 64), this.babyJub.subOrder);
25430
25444
  const R8 = this.babyJub.mulPointEscalar(this.babyJub.Base8, r);
25431
25445
 
@@ -25480,7 +25494,286 @@ class Eddsa {
25480
25494
  }
25481
25495
  }
25482
25496
 
25497
+ const CIRCOM_P =
25498
+ 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
25499
+
25500
+ // Reduce value into [0, m); handles negative inputs.
25501
+ const mod = (value, m = CIRCOM_P) => {
25502
+ const result = value % m;
25503
+ return result >= 0n ? result : result + m;
25504
+ };
25505
+
25506
+ // Modular inverse via extended Euclidean algorithm (a^-1 mod m).
25507
+ const modInverse = (value, m = CIRCOM_P) => {
25508
+ let lm = 1n;
25509
+ let hm = 0n;
25510
+ let low = mod(value, m);
25511
+ let high = m;
25512
+
25513
+ if (low === 0n) throw new Error("Division by zero");
25514
+
25515
+ while (low > 1n) {
25516
+ const remainder = high % low;
25517
+ const quotient = high / low;
25518
+ high = low;
25519
+ low = remainder;
25520
+ const nm = hm - lm * quotient;
25521
+ hm = lm;
25522
+ lm = nm;
25523
+ }
25524
+
25525
+ return lm < 0n ? lm + m : lm;
25526
+ };
25527
+
25528
+ const P = CIRCOM_P;
25529
+
25530
+ // BabyJub base-field arithmetic over CIRCOM_P (same semantics as circomlibjs F).
25531
+ const F = {
25532
+ p: P,
25533
+ zero: 0n,
25534
+ one: 1n,
25535
+ e: (v) => mod(BigInt(v)),
25536
+ add: (a, b) => mod(a + b),
25537
+ sub: (a, b) => mod(a - b),
25538
+ mul: (a, b) => mod(a * b),
25539
+ div: (a, b) => {
25540
+ if (b === 0n) throw new Error("Division by zero in BabyJub field");
25541
+ return mod(a * modInverse(b));
25542
+ },
25543
+ toString: (a) => mod(a).toString(),
25544
+ };
25545
+
25546
+ /**
25547
+ * @typedef {{ X: bigint, Y: bigint, Z: bigint, T: bigint }} ExtPoint
25548
+ */
25549
+
25550
+ // Neutral element in extended coordinates (affine identity 0, 1).
25551
+ const IDENTITY = { X: F.zero, Y: F.one, Z: F.one, T: F.zero };
25552
+
25553
+ // Embed an affine (x, y) point into extended twisted Edwards form.
25554
+ const toExtended = (affine) => {
25555
+ const x = F.e(affine[0]);
25556
+ const y = F.e(affine[1]);
25557
+ return { X: x, Y: y, Z: F.one, T: F.mul(x, y) };
25558
+ };
25559
+
25560
+ // Project an extended point back to affine (x, y) coordinates.
25561
+ const toAffine = (point) => {
25562
+ const zInv = modInverse(point.Z);
25563
+ return [F.mul(point.X, zInv), F.mul(point.Y, zInv)];
25564
+ };
25565
+
25566
+ const A = F.e("168700");
25567
+ const D = F.e("168696");
25568
+
25569
+ // Add two extended points (add-2008-hwcd; no per-step field inversions).
25570
+ const addExtended = (p1, p2) => {
25571
+ const a = F.mul(p1.X, p2.X);
25572
+ const b = F.mul(p1.Y, p2.Y);
25573
+ const c = F.mul(F.mul(p1.T, p2.T), D);
25574
+ const d = F.mul(p1.Z, p2.Z);
25575
+ const e = F.sub(F.mul(F.add(p1.X, p1.Y), F.add(p2.X, p2.Y)), F.add(a, b));
25576
+ const f = F.sub(d, c);
25577
+ const g = F.add(d, c);
25578
+ const h = F.sub(b, F.mul(A, a));
25579
+ return {
25580
+ X: F.mul(e, f),
25581
+ Y: F.mul(g, h),
25582
+ T: F.mul(e, h),
25583
+ Z: F.mul(f, g),
25584
+ };
25585
+ };
25586
+
25587
+ // Double an extended point (dbl-2008-hwcd; no per-step field inversions).
25588
+ const doubleExtended = (p) => {
25589
+ const a = F.mul(p.X, p.X);
25590
+ const b = F.mul(p.Y, p.Y);
25591
+ const c = F.mul(F.mul(p.Z, p.Z), 2n);
25592
+ const d = F.mul(A, a);
25593
+ const e = F.sub(F.mul(F.add(p.X, p.Y), F.add(p.X, p.Y)), F.add(a, b));
25594
+ const g = F.add(d, b);
25595
+ const f = F.sub(g, c);
25596
+ const h = F.sub(d, b);
25597
+ return {
25598
+ X: F.mul(e, f),
25599
+ Y: F.mul(g, h),
25600
+ T: F.mul(e, h),
25601
+ Z: F.mul(f, g),
25602
+ };
25603
+ };
25604
+
25605
+ // Pure-JS BabyJub curve used on React Native (circomlibjs uses WASM instead).
25606
+ class BabyJubRN {
25607
+ static A = A;
25608
+
25609
+ static D = D;
25610
+
25611
+ F = F;
25612
+
25613
+ A = A;
25614
+
25615
+ D = D;
25616
+
25617
+ // Standard BabyJub generator used by EdDSA (matches circomlibjs Base8).
25618
+ Base8 = [
25619
+ F.e(
25620
+ "5299619240641551281634865583518297030282874472190772894086521144482721001553",
25621
+ ),
25622
+ F.e(
25623
+ "16950150798460657717958625567821834550301663161624707787222815936182638968203",
25624
+ ),
25625
+ ];
25626
+
25627
+ // Add two affine curve points.
25628
+ addPoint(a, b) {
25629
+ return toAffine(addExtended(toExtended(a), toExtended(b)));
25630
+ }
25631
+
25632
+ // Scalar multiplication: returns e * base (double-and-add in extended coords).
25633
+ mulPointEscalar(base, e) {
25634
+ let res = IDENTITY;
25635
+ let exp = toExtended(base);
25636
+ let rem = BigInt(e);
25637
+
25638
+ while (rem !== 0n) {
25639
+ if (rem % 2n === 1n) res = addExtended(res, exp);
25640
+ exp = doubleExtended(exp);
25641
+ rem /= 2n;
25642
+ }
25643
+
25644
+ return toAffine(res);
25645
+ }
25646
+ }
25647
+
25648
+ const buildBabyJubRN = () => new BabyJubRN();
25649
+
25650
+ const toBigInt = (v) => {
25651
+ switch (typeof v) {
25652
+ case "bigint":
25653
+ return v;
25654
+ case "boolean":
25655
+ return v ? 1n : 0n;
25656
+ case "number":
25657
+ if (!Number.isInteger(v))
25658
+ throw new TypeError(`Poseidon: non-integer Number ${v}`);
25659
+ return BigInt(v);
25660
+ case "string": {
25661
+ try {
25662
+ return BigInt(v.trim());
25663
+ } catch {
25664
+ throw new TypeError(
25665
+ `Poseidon: cannot parse string "${v}" as an integer`,
25666
+ );
25667
+ }
25668
+ }
25669
+ default:
25670
+ throw new TypeError(`Poseidon.F: unsupported value of type ${typeof v}`);
25671
+ }
25672
+ };
25673
+
25674
+ // poseidon-lite exposes `poseidon1`..`poseidon16`; wrap them in a `buildPoseidon`-shaped
25675
+ // factory (matching the WASM reference) so callers — and the existing
25676
+ // `poseidon.F.toString(...)` pattern — keep working on RN.
25677
+ const buildPoseidon = () => {
25678
+ const poseidon = (inputs, initState = 0, nOut = 1) => {
25679
+ const fn = poseidonLite__namespace[`poseidon${inputs.length}`];
25680
+ if (!fn)
25681
+ throw new Error(`Poseidon: arity ${inputs.length} not supported (1..16)`);
25682
+ const formattedInputs = inputs.map((v) => toBigInt(v));
25683
+
25684
+ if (nOut > 1) {
25685
+ const results = fn(formattedInputs, nOut);
25686
+ return results.map((v) => BigInt(v));
25687
+ }
25688
+
25689
+ const res = fn(formattedInputs);
25690
+ return BigInt(res);
25691
+ };
25692
+ poseidon.F = {
25693
+ toString: (v) => toBigInt(v).toString(),
25694
+ e: (v) => toBigInt(v),
25695
+ eq: (a, b) => toBigInt(a) === toBigInt(b),
25696
+ };
25697
+ return poseidon;
25698
+ };
25699
+
25700
+ /* eslint-disable no-bitwise */
25701
+ // React Native port of circomlibjs-hinkal-fork/src/eddsa.js (Poseidon EdDSA over BabyJubJub).
25702
+
25703
+ const BABYJUB_ORDER = 21888242871839275222246405745257275088614511777268538073601725287587578984328n;
25704
+ const SUB_ORDER = BABYJUB_ORDER / 8n;
25705
+
25706
+ const leBuff2int = (buff, offset = 0, length = buff.length - offset) => {
25707
+ let result = 0n;
25708
+ for (let i = length - 1; i >= 0; i -= 1) {
25709
+ result = (result << 8n) + BigInt(buff[offset + i]);
25710
+ }
25711
+ return result;
25712
+ };
25713
+
25714
+ const toRprLE = (buff, offset, value, length) => {
25715
+ let v = mod(value);
25716
+ for (let i = 0; i < length; i += 1) {
25717
+ buff[offset + i] = Number(v & 0xffn);
25718
+ v >>= 8n;
25719
+ }
25720
+ };
25721
+
25722
+ const modSubOrder = (value) => mod(value, SUB_ORDER);
25723
+
25724
+ const pruneBuffer = (buff) => {
25725
+ const out = new Uint8Array(buff);
25726
+ out[0] = out[0] & 0xf8;
25727
+ out[31] = out[31] & 0x7f;
25728
+ out[31] = out[31] | 0x40;
25729
+ return out;
25730
+ };
25731
+
25732
+ /**
25733
+ * @typedef {((inputs: bigint[]) => bigint) & { F: { toString: (v: bigint | number | string) => string } }} PoseidonFn
25734
+ */
25735
+
25736
+ class EddsaRN {
25737
+ constructor(babyJub, poseidon) {
25738
+ this.babyJub = babyJub;
25739
+ this.poseidon = poseidon;
25740
+ }
25741
+
25742
+ prv2pub(prv) {
25743
+ const sBuff = pruneBuffer(blake1_js.blake512(prv).slice(0, 32));
25744
+ const s = leBuff2int(sBuff, 0, 32);
25745
+ return this.babyJub.mulPointEscalar(this.babyJub.Base8, s / 8n);
25746
+ }
25747
+
25748
+ signPoseidon(prv, msg) {
25749
+ const sBuff = pruneBuffer(blake1_js.blake512(prv));
25750
+ const s = leBuff2int(sBuff, 0, 32);
25751
+ const A = this.babyJub.mulPointEscalar(this.babyJub.Base8, s / 8n);
25752
+
25753
+ const composeBuff = new Uint8Array(64);
25754
+ composeBuff.set(sBuff.slice(32), 0);
25755
+ toRprLE(composeBuff, 32, msg, 32);
25756
+
25757
+ const rBuff = blake1_js.blake512(composeBuff);
25758
+ const r = modSubOrder(leBuff2int(rBuff, 0, 64));
25759
+ const R8 = this.babyJub.mulPointEscalar(this.babyJub.Base8, r);
25760
+
25761
+ const hm = this.poseidon([R8[0], R8[1], A[0], A[1], msg]);
25762
+ const hms = mod(BigInt(this.poseidon.F.toString(hm)));
25763
+ const S = modSubOrder(r + modSubOrder(hms * s));
25764
+
25765
+ return { R8, S };
25766
+ }
25767
+ }
25768
+
25769
+ const buildEddsaRN = async () => {
25770
+ return new EddsaRN(buildBabyJubRN(), buildPoseidon());
25771
+ };
25772
+
25773
+ exports.buildBabyJubRN = buildBabyJubRN;
25483
25774
  exports.buildBabyjub = buildBabyJub;
25484
25775
  exports.buildEddsa = buildEddsa;
25485
- exports.buildPoseidon = buildPoseidon;
25776
+ exports.buildEddsaRN = buildEddsaRN;
25777
+ exports.buildPoseidon = buildPoseidon$1;
25778
+ exports.buildPoseidonRN = buildPoseidon;
25486
25779
  exports.buildPoseidonWasm = buildPoseidonWasm;
package/main.js CHANGED
@@ -1,7 +1,11 @@
1
- export {default as buildBabyjub} from "./src/babyjub.js";
1
+ export { default as buildBabyjub } from "./src/babyjub.js";
2
2
 
3
- export {default as buildEddsa} from "./src/eddsa.js";
3
+ export { default as buildEddsa } from "./src/eddsa.js";
4
4
 
5
5
  export { buildPoseidon, buildPoseidonWasm } from "./src/poseidon_wasm.js";
6
6
 
7
+ export { buildEddsaRN } from "./src/EddsaRN.js";
7
8
 
9
+ export { buildBabyJubRN } from "./src/babyjubRN.js";
10
+
11
+ export { buildPoseidon as buildPoseidonRN } from "./src/poseidonRN.js";
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "import": "./main.js",
8
8
  "require": "./build/main.cjs"
9
9
  },
10
- "version": "0.0.9",
10
+ "version": "0.0.11",
11
11
  "description": "Javascript library to work with circomlib",
12
12
  "scripts": {
13
13
  "test": "mocha",
@@ -31,7 +31,8 @@
31
31
  "rollup": "^4.60.4"
32
32
  },
33
33
  "dependencies": {
34
+ "@noble/hashes": "^2.2.0",
34
35
  "ffjavascript": "^0.3.0",
35
- "blake-hash": "^2.0.0"
36
+ "poseidon-lite": "^0.3.0"
36
37
  }
37
38
  }
package/src/EddsaRN.js ADDED
@@ -0,0 +1,76 @@
1
+ /* eslint-disable no-bitwise */
2
+ // React Native port of circomlibjs-hinkal-fork/src/eddsa.js (Poseidon EdDSA over BabyJubJub).
3
+ import { blake512 } from '@noble/hashes/blake1.js';
4
+ import { buildBabyJubRN } from './babyjubRN.js';
5
+ import { buildPoseidon as buildPoseidonRN } from './poseidonRN.js';
6
+ import { mod } from './bigint-math.utils.js';
7
+
8
+ const BABYJUB_ORDER = 21888242871839275222246405745257275088614511777268538073601725287587578984328n;
9
+ const SUB_ORDER = BABYJUB_ORDER / 8n;
10
+
11
+ const leBuff2int = (buff, offset = 0, length = buff.length - offset) => {
12
+ let result = 0n;
13
+ for (let i = length - 1; i >= 0; i -= 1) {
14
+ result = (result << 8n) + BigInt(buff[offset + i]);
15
+ }
16
+ return result;
17
+ };
18
+
19
+ const toRprLE = (buff, offset, value, length) => {
20
+ let v = mod(value);
21
+ for (let i = 0; i < length; i += 1) {
22
+ buff[offset + i] = Number(v & 0xffn);
23
+ v >>= 8n;
24
+ }
25
+ };
26
+
27
+ const modSubOrder = (value) => mod(value, SUB_ORDER);
28
+
29
+ const pruneBuffer = (buff) => {
30
+ const out = new Uint8Array(buff);
31
+ out[0] = out[0] & 0xf8;
32
+ out[31] = out[31] & 0x7f;
33
+ out[31] = out[31] | 0x40;
34
+ return out;
35
+ };
36
+
37
+ /**
38
+ * @typedef {((inputs: bigint[]) => bigint) & { F: { toString: (v: bigint | number | string) => string } }} PoseidonFn
39
+ */
40
+
41
+ export class EddsaRN {
42
+ constructor(babyJub, poseidon) {
43
+ this.babyJub = babyJub;
44
+ this.poseidon = poseidon;
45
+ }
46
+
47
+ prv2pub(prv) {
48
+ const sBuff = pruneBuffer(blake512(prv).slice(0, 32));
49
+ const s = leBuff2int(sBuff, 0, 32);
50
+ return this.babyJub.mulPointEscalar(this.babyJub.Base8, s / 8n);
51
+ }
52
+
53
+ signPoseidon(prv, msg) {
54
+ const sBuff = pruneBuffer(blake512(prv));
55
+ const s = leBuff2int(sBuff, 0, 32);
56
+ const A = this.babyJub.mulPointEscalar(this.babyJub.Base8, s / 8n);
57
+
58
+ const composeBuff = new Uint8Array(64);
59
+ composeBuff.set(sBuff.slice(32), 0);
60
+ toRprLE(composeBuff, 32, msg, 32);
61
+
62
+ const rBuff = blake512(composeBuff);
63
+ const r = modSubOrder(leBuff2int(rBuff, 0, 64));
64
+ const R8 = this.babyJub.mulPointEscalar(this.babyJub.Base8, r);
65
+
66
+ const hm = this.poseidon([R8[0], R8[1], A[0], A[1], msg]);
67
+ const hms = mod(BigInt(this.poseidon.F.toString(hm)));
68
+ const S = modSubOrder(r + modSubOrder(hms * s));
69
+
70
+ return { R8, S };
71
+ }
72
+ }
73
+
74
+ export const buildEddsaRN = async () => {
75
+ return new EddsaRN(buildBabyJubRN(), buildPoseidonRN());
76
+ };
@@ -0,0 +1,124 @@
1
+ import { CIRCOM_P } from "./protocol.constants.js";
2
+ import { mod, modInverse } from "./bigint-math.utils.js";
3
+
4
+ const P = CIRCOM_P;
5
+
6
+ // BabyJub base-field arithmetic over CIRCOM_P (same semantics as circomlibjs F).
7
+ const F = {
8
+ p: P,
9
+ zero: 0n,
10
+ one: 1n,
11
+ e: (v) => mod(BigInt(v)),
12
+ add: (a, b) => mod(a + b),
13
+ sub: (a, b) => mod(a - b),
14
+ mul: (a, b) => mod(a * b),
15
+ div: (a, b) => {
16
+ if (b === 0n) throw new Error("Division by zero in BabyJub field");
17
+ return mod(a * modInverse(b));
18
+ },
19
+ toString: (a) => mod(a).toString(),
20
+ };
21
+
22
+ /**
23
+ * @typedef {{ X: bigint, Y: bigint, Z: bigint, T: bigint }} ExtPoint
24
+ */
25
+
26
+ // Neutral element in extended coordinates (affine identity 0, 1).
27
+ const IDENTITY = { X: F.zero, Y: F.one, Z: F.one, T: F.zero };
28
+
29
+ // Embed an affine (x, y) point into extended twisted Edwards form.
30
+ const toExtended = (affine) => {
31
+ const x = F.e(affine[0]);
32
+ const y = F.e(affine[1]);
33
+ return { X: x, Y: y, Z: F.one, T: F.mul(x, y) };
34
+ };
35
+
36
+ // Project an extended point back to affine (x, y) coordinates.
37
+ const toAffine = (point) => {
38
+ const zInv = modInverse(point.Z);
39
+ return [F.mul(point.X, zInv), F.mul(point.Y, zInv)];
40
+ };
41
+
42
+ const A = F.e("168700");
43
+ const D = F.e("168696");
44
+
45
+ // Add two extended points (add-2008-hwcd; no per-step field inversions).
46
+ const addExtended = (p1, p2) => {
47
+ const a = F.mul(p1.X, p2.X);
48
+ const b = F.mul(p1.Y, p2.Y);
49
+ const c = F.mul(F.mul(p1.T, p2.T), D);
50
+ const d = F.mul(p1.Z, p2.Z);
51
+ const e = F.sub(F.mul(F.add(p1.X, p1.Y), F.add(p2.X, p2.Y)), F.add(a, b));
52
+ const f = F.sub(d, c);
53
+ const g = F.add(d, c);
54
+ const h = F.sub(b, F.mul(A, a));
55
+ return {
56
+ X: F.mul(e, f),
57
+ Y: F.mul(g, h),
58
+ T: F.mul(e, h),
59
+ Z: F.mul(f, g),
60
+ };
61
+ };
62
+
63
+ // Double an extended point (dbl-2008-hwcd; no per-step field inversions).
64
+ const doubleExtended = (p) => {
65
+ const a = F.mul(p.X, p.X);
66
+ const b = F.mul(p.Y, p.Y);
67
+ const c = F.mul(F.mul(p.Z, p.Z), 2n);
68
+ const d = F.mul(A, a);
69
+ const e = F.sub(F.mul(F.add(p.X, p.Y), F.add(p.X, p.Y)), F.add(a, b));
70
+ const g = F.add(d, b);
71
+ const f = F.sub(g, c);
72
+ const h = F.sub(d, b);
73
+ return {
74
+ X: F.mul(e, f),
75
+ Y: F.mul(g, h),
76
+ T: F.mul(e, h),
77
+ Z: F.mul(f, g),
78
+ };
79
+ };
80
+
81
+ // Pure-JS BabyJub curve used on React Native (circomlibjs uses WASM instead).
82
+ export class BabyJubRN {
83
+ static A = A;
84
+
85
+ static D = D;
86
+
87
+ F = F;
88
+
89
+ A = A;
90
+
91
+ D = D;
92
+
93
+ // Standard BabyJub generator used by EdDSA (matches circomlibjs Base8).
94
+ Base8 = [
95
+ F.e(
96
+ "5299619240641551281634865583518297030282874472190772894086521144482721001553",
97
+ ),
98
+ F.e(
99
+ "16950150798460657717958625567821834550301663161624707787222815936182638968203",
100
+ ),
101
+ ];
102
+
103
+ // Add two affine curve points.
104
+ addPoint(a, b) {
105
+ return toAffine(addExtended(toExtended(a), toExtended(b)));
106
+ }
107
+
108
+ // Scalar multiplication: returns e * base (double-and-add in extended coords).
109
+ mulPointEscalar(base, e) {
110
+ let res = IDENTITY;
111
+ let exp = toExtended(base);
112
+ let rem = BigInt(e);
113
+
114
+ while (rem !== 0n) {
115
+ if (rem % 2n === 1n) res = addExtended(res, exp);
116
+ exp = doubleExtended(exp);
117
+ rem /= 2n;
118
+ }
119
+
120
+ return toAffine(res);
121
+ }
122
+ }
123
+
124
+ export const buildBabyJubRN = () => new BabyJubRN();
@@ -0,0 +1,29 @@
1
+ import { CIRCOM_P } from "./protocol.constants.js";
2
+
3
+ // Reduce value into [0, m); handles negative inputs.
4
+ export const mod = (value, m = CIRCOM_P) => {
5
+ const result = value % m;
6
+ return result >= 0n ? result : result + m;
7
+ };
8
+
9
+ // Modular inverse via extended Euclidean algorithm (a^-1 mod m).
10
+ export const modInverse = (value, m = CIRCOM_P) => {
11
+ let lm = 1n;
12
+ let hm = 0n;
13
+ let low = mod(value, m);
14
+ let high = m;
15
+
16
+ if (low === 0n) throw new Error("Division by zero");
17
+
18
+ while (low > 1n) {
19
+ const remainder = high % low;
20
+ const quotient = high / low;
21
+ high = low;
22
+ low = remainder;
23
+ const nm = hm - lm * quotient;
24
+ hm = lm;
25
+ lm = nm;
26
+ }
27
+
28
+ return lm < 0n ? lm + m : lm;
29
+ };
package/src/eddsa.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Scalar, utils } from "ffjavascript";
2
2
  import buildBabyJub from "./babyjub.js";
3
3
  import { buildPoseidon } from "./poseidon_wasm.js";
4
- import createBlakeHash from "blake-hash";
4
+ import { blake512 } from "@noble/hashes/blake1.js";
5
5
 
6
6
  export default async function buildEddsa() {
7
7
  const babyJub = await buildBabyJub("bn128");
@@ -24,9 +24,7 @@ class Eddsa {
24
24
  }
25
25
 
26
26
  prv2pub(prv) {
27
- const sBuff = this.pruneBuffer(
28
- createBlakeHash("blake512").update(prv).digest().slice(0, 32),
29
- );
27
+ const sBuff = this.pruneBuffer(blake512(prv).slice(0, 32));
30
28
  let s = utils.leBuff2int(sBuff);
31
29
  const A = this.babyJub.mulPointEscalar(
32
30
  this.babyJub.Base8,
@@ -37,9 +35,7 @@ class Eddsa {
37
35
 
38
36
  signPoseidon(prv, msg) {
39
37
  const F = this.babyJub.F;
40
- const sBuff = this.pruneBuffer(
41
- createBlakeHash("blake512").update(Buffer.from(prv)).digest(),
42
- );
38
+ const sBuff = this.pruneBuffer(blake512(prv));
43
39
  const s = Scalar.fromRprLE(sBuff, 0, 32);
44
40
  const A = this.babyJub.mulPointEscalar(
45
41
  this.babyJub.Base8,
@@ -49,9 +45,7 @@ class Eddsa {
49
45
  const composeBuff = new Uint8Array(32 + msg.length);
50
46
  composeBuff.set(sBuff.slice(32), 0);
51
47
  F.toRprLE(composeBuff, 32, msg);
52
- const rBuff = createBlakeHash("blake512")
53
- .update(Buffer.from(composeBuff))
54
- .digest();
48
+ const rBuff = blake512(composeBuff);
55
49
  let r = Scalar.mod(Scalar.fromRprLE(rBuff, 0, 64), this.babyJub.subOrder);
56
50
  const R8 = this.babyJub.mulPointEscalar(this.babyJub.Base8, r);
57
51
 
@@ -0,0 +1,51 @@
1
+ import * as poseidonLite from "poseidon-lite";
2
+
3
+ const toBigInt = (v) => {
4
+ switch (typeof v) {
5
+ case "bigint":
6
+ return v;
7
+ case "boolean":
8
+ return v ? 1n : 0n;
9
+ case "number":
10
+ if (!Number.isInteger(v))
11
+ throw new TypeError(`Poseidon: non-integer Number ${v}`);
12
+ return BigInt(v);
13
+ case "string": {
14
+ try {
15
+ return BigInt(v.trim());
16
+ } catch {
17
+ throw new TypeError(
18
+ `Poseidon: cannot parse string "${v}" as an integer`,
19
+ );
20
+ }
21
+ }
22
+ default:
23
+ throw new TypeError(`Poseidon.F: unsupported value of type ${typeof v}`);
24
+ }
25
+ };
26
+
27
+ // poseidon-lite exposes `poseidon1`..`poseidon16`; wrap them in a `buildPoseidon`-shaped
28
+ // factory (matching the WASM reference) so callers — and the existing
29
+ // `poseidon.F.toString(...)` pattern — keep working on RN.
30
+ export const buildPoseidon = () => {
31
+ const poseidon = (inputs, initState = 0, nOut = 1) => {
32
+ const fn = poseidonLite[`poseidon${inputs.length}`];
33
+ if (!fn)
34
+ throw new Error(`Poseidon: arity ${inputs.length} not supported (1..16)`);
35
+ const formattedInputs = inputs.map((v) => toBigInt(v));
36
+
37
+ if (nOut > 1) {
38
+ const results = fn(formattedInputs, nOut);
39
+ return results.map((v) => BigInt(v));
40
+ }
41
+
42
+ const res = fn(formattedInputs);
43
+ return BigInt(res);
44
+ };
45
+ poseidon.F = {
46
+ toString: (v) => toBigInt(v).toString(),
47
+ e: (v) => toBigInt(v),
48
+ eq: (a, b) => toBigInt(a) === toBigInt(b),
49
+ };
50
+ return poseidon;
51
+ };
@@ -0,0 +1,2 @@
1
+ export const CIRCOM_P =
2
+ 21888242871839275222246405745257275088548364400416034343698204186575808495617n;