@silvana-one/mina-utils
Version:
Silvana Mina Utils
72 lines • 3.38 kB
JavaScript
import { Field } from "o1js";
import { getR, Fr } from "./constants.js";
import { rScalarPowProvable } from "./exp.js";
// Create R constant for ZkProgram use (needs to be available at module level for provable code)
export const R = getR();
// ----- constants taken from Move code (big‑endian hex) -----
export const S = Fr.from(0x1582695da6689f26db7bb3eb32907ecd0ac3af032aefad31a069352705f0d459n);
const P = Field(20359658106300430391853594957854653514501797417378649347544016260949017072120n);
const P2 = P.mul(P);
// ----- helpers -----
export function scalar(n) {
return Fr.from(n);
}
export function blsCommitment(element) {
return element.value[0]
.add(element.value[1].mul(P))
.add(element.value[1].mul(P2));
}
// inner: digest one struct
export function digestStruct(fields) {
let d = Fr.from(0n).assertAlmostReduced();
for (const f of fields) {
const prod = d.mul(S); // returns Unreduced
d = prod.add(f).assertAlmostReduced(); // reduce for next iteration
}
return d.assertCanonical();
}
// outer: commit whole table (vector of digests)
export function commit(table) {
let acc = Fr.from(0n).assertAlmostReduced();
const r = getR(); // Get R once, not in every iteration
// Iterate in reverse order so that table[i] gets coefficient R^i
for (let i = table.length - 1; i >= 0; i--) {
const prod = acc.mul(r); // returns Unreduced
acc = prod.add(table[i]).assertAlmostReduced(); // reduce for next iteration
}
return acc.assertCanonical();
}
// constant‑time single‑field update using struct digest recalculation (non-provable version)
// export function update(
// oldTableCommitment: AlmostReducedElement,
// oldStructDigest: AlmostReducedElement,
// newStructDigest: AlmostReducedElement,
// index: number
// ): AlmostReducedElement {
// // The table commitment formula in commit() now produces:
// // table[0]*R^0 + table[1]*R^1 + table[2]*R^2 + ... + table[i]*R^i
// // So position i has coefficient R^i
// // Position i has coefficient R^i - use optimized lookup table exponentiation
// const rPowI = rScalarPow(index).assertCanonical();
// // Calculate the change: new_commitment = old_commitment + (new_struct - old_struct) * R^i
// const structDelta = newStructDigest
// .sub(oldStructDigest)
// .assertAlmostReduced();
// const tableDelta = structDelta.mul(rPowI).assertAlmostReduced();
// return oldTableCommitment.add(tableDelta).assertAlmostReduced();
// }
// constant‑time single‑field update using struct digest recalculation (provable version)
export function update(oldTableCommitment, oldStructDigest, newStructDigest, index) {
// The table commitment formula in commit() now produces:
// table[0]*R^0 + table[1]*R^1 + table[2]*R^2 + ... + table[i]*R^i
// So position i has coefficient R^i
// Position i has coefficient R^i - use provable lookup table exponentiation
const rPowI = rScalarPowProvable(index).assertCanonical();
// Calculate the change: new_commitment = old_commitment + (new_struct - old_struct) * R^i
const structDelta = newStructDigest
.sub(oldStructDigest)
.assertAlmostReduced();
const tableDelta = structDelta.mul(rPowI).assertAlmostReduced();
return oldTableCommitment.add(tableDelta).assertCanonical();
}
//# sourceMappingURL=commitment.js.map