@silvana-one/mina-utils 1.0.23 → 1.0.25

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.
Files changed (54) hide show
  1. package/dist/node/commitment/commitment.d.ts +11 -0
  2. package/dist/node/commitment/commitment.js +72 -0
  3. package/dist/node/commitment/commitment.js.map +1 -0
  4. package/dist/node/commitment/constants.d.ts +11 -0
  5. package/dist/node/commitment/constants.js +3125 -0
  6. package/dist/node/commitment/constants.js.map +1 -0
  7. package/dist/node/commitment/exp.d.ts +5 -0
  8. package/dist/node/commitment/exp.js +106 -0
  9. package/dist/node/commitment/exp.js.map +1 -0
  10. package/dist/node/commitment/index.d.ts +5 -0
  11. package/dist/node/commitment/index.js +6 -0
  12. package/dist/node/commitment/index.js.map +1 -0
  13. package/dist/node/commitment/tree.d.ts +6 -0
  14. package/dist/node/commitment/tree.js +17 -0
  15. package/dist/node/commitment/tree.js.map +1 -0
  16. package/dist/node/commitment/witnesses.d.ts +6 -0
  17. package/dist/node/commitment/witnesses.js +3085 -0
  18. package/dist/node/commitment/witnesses.js.map +1 -0
  19. package/dist/node/index.cjs +12518 -2
  20. package/dist/node/index.d.ts +1 -0
  21. package/dist/node/index.js +1 -0
  22. package/dist/node/index.js.map +1 -1
  23. package/dist/tsconfig.tsbuildinfo +1 -1
  24. package/dist/tsconfig.web.tsbuildinfo +1 -1
  25. package/dist/web/commitment/commitment.d.ts +11 -0
  26. package/dist/web/commitment/commitment.js +72 -0
  27. package/dist/web/commitment/commitment.js.map +1 -0
  28. package/dist/web/commitment/constants.d.ts +11 -0
  29. package/dist/web/commitment/constants.js +3125 -0
  30. package/dist/web/commitment/constants.js.map +1 -0
  31. package/dist/web/commitment/exp.d.ts +5 -0
  32. package/dist/web/commitment/exp.js +106 -0
  33. package/dist/web/commitment/exp.js.map +1 -0
  34. package/dist/web/commitment/index.d.ts +5 -0
  35. package/dist/web/commitment/index.js +6 -0
  36. package/dist/web/commitment/index.js.map +1 -0
  37. package/dist/web/commitment/tree.d.ts +6 -0
  38. package/dist/web/commitment/tree.js +17 -0
  39. package/dist/web/commitment/tree.js.map +1 -0
  40. package/dist/web/commitment/witnesses.d.ts +6 -0
  41. package/dist/web/commitment/witnesses.js +3085 -0
  42. package/dist/web/commitment/witnesses.js.map +1 -0
  43. package/dist/web/index.d.ts +1 -0
  44. package/dist/web/index.js +1 -0
  45. package/dist/web/index.js.map +1 -1
  46. package/package.json +5 -5
  47. package/src/commitment/README.md +3 -0
  48. package/src/commitment/commitment.ts +149 -0
  49. package/src/commitment/constants.ts +3135 -0
  50. package/src/commitment/exp.ts +139 -0
  51. package/src/commitment/index.ts +5 -0
  52. package/src/commitment/tree.ts +18 -0
  53. package/src/commitment/witnesses.ts +3088 -0
  54. package/src/index.ts +1 -0
@@ -0,0 +1,139 @@
1
+ /// Optimized scalar exponentiation using lookup tables
2
+
3
+ import {
4
+ getR,
5
+ getTable0Entry,
6
+ getTable1Entry,
7
+ getTable2Entry,
8
+ } from "./constants.js";
9
+ import { UInt32, Field, Gadgets, Provable, assert } from "o1js";
10
+ import {
11
+ WITNESSES0,
12
+ WITNESSES1,
13
+ WITNESSES2,
14
+ TABLE0_ROOT,
15
+ TABLE1_ROOT,
16
+ TABLE2_ROOT,
17
+ } from "./witnesses.js";
18
+ import { Witness } from "./tree.js";
19
+ import { deserializeFields } from "../utils/index.js";
20
+ import { blsCommitment, CanonicalElement } from "./commitment.js";
21
+ import { Fr } from "./constants.js";
22
+
23
+ /// Optimized exponentiation using three 1024-element lookup tables
24
+ /// Computes R^exp using base-1024 decomposition:
25
+ /// exp = i0 + 1024*i1 + 1024^2*i2
26
+ /// R^exp = TABLE2[i2] * TABLE1[i1] * TABLE0[i0]
27
+ ///
28
+ /// Time complexity: O(1) - constant time with 3 table lookups + 2 multiplications
29
+ /// Space complexity: 3 * 1024 * 32 bytes = 96 KiB for all tables
30
+ /// Range: supports exponents up to 1024^3 - 1 = 1,073,741,823
31
+ export function rScalarPow(exp: number | bigint): CanonicalElement {
32
+ const expNum = typeof exp === "bigint" ? Number(exp) : exp;
33
+
34
+ if (expNum < 0 || expNum >= 1024 ** 3) {
35
+ throw new Error(`Exponent out of range: ${expNum}`);
36
+ }
37
+
38
+ // Decompose exponent in base-1024 (10 bits per component)
39
+ const i0 = expNum & 0x3ff; // exp mod 1024 (lowest 10 bits)
40
+ const i1 = (expNum >> 10) & 0x3ff; // next 10 bits
41
+ const i2 = (expNum >> 20) & 0x3ff; // highest 10 bits
42
+
43
+ // Constant-time table lookups
44
+ const t0 = getTable0Entry(i0);
45
+ const t1 = getTable1Entry(i1);
46
+ const t2 = getTable2Entry(i2);
47
+
48
+ // Combine results with 2 field multiplications
49
+ let result = t2.mul(t1).assertCanonical(); // R^(1024^2*i2 + 1024*i1)
50
+ result = result.mul(t0).assertCanonical(); // + i0
51
+
52
+ return result;
53
+ }
54
+
55
+ /// Provable version of scalar exponentiation for use in ZkPrograms
56
+ /// Uses o1js gadgets for bitwise operations instead of JavaScript operators
57
+ export function rScalarPowProvable(exp: UInt32): CanonicalElement {
58
+ // Range check to ensure exponent is within valid bounds
59
+ assert(
60
+ exp.lessThan(UInt32.from(1024 * 1024 * 1024)),
61
+ "Exponent out of range (non-provable check)"
62
+ );
63
+
64
+ // Decompose exponent in base-1024 using provable bitwise operations
65
+ // Each component is 10 bits, so we extract 3 components of 10 bits each
66
+
67
+ // Create bitmask for 10 bits (0x3FF = 1023)
68
+ const mask = Field(0x3ff);
69
+
70
+ // Extract components using provable bitwise operations
71
+ const i0 = Gadgets.and(exp.value, mask, 10); // exp & 0x3FF (lowest 10 bits)
72
+ const shifted10 = Gadgets.rightShift64(exp.value, 10); // exp >> 10
73
+ const i1 = Gadgets.and(shifted10, mask, 10); // (exp >> 10) & 0x3FF
74
+ const shifted20 = Gadgets.rightShift64(exp.value, 20); // exp >> 20
75
+ const i2 = Gadgets.and(shifted20, mask, 10); // (exp >> 20) & 0x3FF
76
+
77
+ // Convert Field indices to witness values for table lookups
78
+ // TODO: use lookup tables instead of witness to make code fully provable
79
+ // or add all TABLEX to Merkle tree and check the value in the tree
80
+ const t0 = Provable.witness(Fr.Canonical.provable, () => {
81
+ const idx = Number(i0.toBigInt());
82
+ return getTable0Entry(idx);
83
+ });
84
+ const witness0 = Provable.witness(Witness, () => {
85
+ const idx = Number(i0.toBigInt());
86
+ return Witness.fromFields(deserializeFields(WITNESSES0[idx]));
87
+ });
88
+ const root0 = Field(TABLE0_ROOT);
89
+ const witness0root = witness0.calculateRoot(blsCommitment(t0));
90
+ const witness0index = witness0.calculateIndex();
91
+ witness0root.assertEquals(root0, "Witness0 root should match root0");
92
+ witness0index.assertEquals(i0, "Witness0 index should match i0");
93
+
94
+ const t1 = Provable.witness(Fr.Canonical.provable, () => {
95
+ const idx = Number(i1.toBigInt());
96
+ return getTable1Entry(idx);
97
+ });
98
+ const witness1 = Provable.witness(Witness, () => {
99
+ const idx = Number(i1.toBigInt());
100
+ return Witness.fromFields(deserializeFields(WITNESSES1[idx]));
101
+ });
102
+ const root1 = Field(TABLE1_ROOT);
103
+ const witness1root = witness1.calculateRoot(blsCommitment(t1));
104
+ const witness1index = witness1.calculateIndex();
105
+ witness1root.assertEquals(root1, "Witness1 root should match root1");
106
+ witness1index.assertEquals(i1, "Witness1 index should match i1");
107
+
108
+ const t2 = Provable.witness(Fr.Canonical.provable, () => {
109
+ const idx = Number(i2.toBigInt());
110
+ return getTable2Entry(idx);
111
+ });
112
+ const witness2 = Provable.witness(Witness, () => {
113
+ const idx = Number(i2.toBigInt());
114
+ return Witness.fromFields(deserializeFields(WITNESSES2[idx]));
115
+ });
116
+ const root2 = Field(TABLE2_ROOT);
117
+ const witness2root = witness2.calculateRoot(blsCommitment(t2));
118
+ const witness2index = witness2.calculateIndex();
119
+ witness2root.assertEquals(root2, "Witness2 root should match root2");
120
+ witness2index.assertEquals(i2, "Witness2 index should match i2");
121
+
122
+ // Combine results with 2 field multiplications
123
+ let result = t2.mul(t1).assertCanonical(); // R^(1024^2*i2 + 1024*i1)
124
+ result = result.mul(t0).assertCanonical(); // + i0
125
+
126
+ return result;
127
+ }
128
+
129
+ /// Legacy function (inefficient, use rScalarPow instead)
130
+ export function rScalarPowLegacy(exp: number): CanonicalElement {
131
+ let acc = Fr.from(1n); // Start with 1
132
+ const r = getR(); // Get R when needed, not at startup
133
+
134
+ for (let i = 0; i < exp; i++) {
135
+ acc = acc.mul(r).assertCanonical();
136
+ }
137
+
138
+ return acc;
139
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./commitment.js";
2
+ export * from "./constants.js";
3
+ export * from "./exp.js";
4
+ export * from "./tree.js";
5
+ export * from "./witnesses.js";
@@ -0,0 +1,18 @@
1
+ import { MerkleTree, MerkleWitness, assert } from "o1js";
2
+ import { Fr } from "./constants.js";
3
+ import { blsCommitment } from "./commitment.js";
4
+
5
+ const TREE_DEPTH = 11;
6
+ const TABLE_SIZE = 1024;
7
+ export class Witness extends MerkleWitness(TREE_DEPTH) {}
8
+
9
+ export function createMerkleTree(table: bigint[]) {
10
+ assert(table.length === TABLE_SIZE, "Table size must be 1024");
11
+ const tree = new MerkleTree(TREE_DEPTH);
12
+ assert(tree.leafCount === BigInt(TABLE_SIZE), "Tree size must be 1024");
13
+
14
+ for (let i = 0; i < TABLE_SIZE; i++) {
15
+ tree.setLeaf(BigInt(i), blsCommitment(Fr.from(table[i])));
16
+ }
17
+ return tree;
18
+ }