ffjavascript
ffjavascript is a Finite Field Library implemented in JavaScript, designed for cryptographic applications, particularly those involving zk-SNARKs and other zero-knowledge proof systems. It provides core functionalities for performing arithmetic operations within finite fields, which are fundamental building blocks for many advanced cryptographic primitives. The library is currently at version 0.3.1 and sees an active, though not rapid, release cadence with minor updates and fixes. It is distinguished by its broad environment compatibility, supporting NodeJS, browser environments, Chrome Extensions, and Metamask Snaps (with SES compatibility), making it versatile for both backend and frontend cryptographic computations. Its primary differentiator is its focus on providing the underlying finite field arithmetic necessary for complex cryptographic protocols, often serving as a dependency for higher-level SNARK libraries.
Common errors
-
Error: Module not found: Error: Can't resolve 'ffjavascript' in '[your-project-path]'
cause Webpack or other bundlers are failing to resolve the `ffjavascript` module, often due to chunking optimizations or incorrect module resolution paths.fixEnsure your webpack configuration disables `splitChunks` by adding `optimization: { splitChunks: false }` to your `module.exports` in `webpack.config.js` or equivalent. -
TypeError: Cannot read properties of undefined (reading 'e') at Function.buildBn128
cause The field builder function (e.g., `buildBn128`) often returns a Promise that needs to be awaited before the field object can be used.fixAlways use `await` when calling `buildBn128()` or similar field builder functions, as they are asynchronous. Example: `const Fr = await buildBn128();`.
Warnings
- gotcha When using ffjavascript in Webpack-based projects (e.g., Next.js, Angular), you may encounter issues related to module chunking. The library's internal structure or dependencies might conflict with Webpack's default `splitChunks` optimization.
- breaking Version 0.3.0 introduced a fix that renames internal `eval` usage to ensure compatibility with SES (Secure EcmaScript) environments, such as Metamask Snaps. This change might break applications that relied on specific internal behaviors of `eval` or were not prepared for a more restricted execution environment.
- gotcha ffjavascript transitioned to being primarily an ES Module (ESM) after version 0.3.0, while still providing CommonJS (CJS) compatibility for Node.js via its `exports` field. Incorrect import syntax (e.g., using `require()` for ESM-only contexts or `import` in CJS-only environments) can lead to module resolution errors.
Install
-
npm install ffjavascript -
yarn add ffjavascript -
pnpm add ffjavascript
Imports
- buildBn128
const { buildBn128 } = require('ffjavascript');import { buildBn128 } from 'ffjavascript'; - buildBabyJub
import buildBabyJub from 'ffjavascript';
import { buildBabyJub } from 'ffjavascript'; - ThreadManager
const ThreadManager = require('ffjavascript').ThreadManager;import { ThreadManager } from 'ffjavascript';
Quickstart
import { buildBn128 } from 'ffjavascript';
async function runFieldOperations() {
console.log('Initializing BN128 Finite Field...');
const Fr = await buildBn128();
console.log('Field initialized successfully.');
// Create some field elements
const a = Fr.e(10);
const b = Fr.e(20);
const c = Fr.e('1234567890123456789012345678901234567890'); // Larger number as string
console.log(`a: ${Fr.toString(a)}`);
console.log(`b: ${Fr.toString(b)}`);
console.log(`c: ${Fr.toString(c)}`);
// Perform basic arithmetic operations
const sum = Fr.add(a, b);
const product = Fr.mul(a, b);
const diff = Fr.sub(b, a);
const inv = Fr.inv(a);
const div = Fr.div(b, a);
console.log(`a + b = ${Fr.toString(sum)}`);
console.log(`a * b = ${Fr.toString(product)}`);
console.log(`b - a = ${Fr.toString(diff)}`);
console.log(`1 / a = ${Fr.toString(inv)}`);
console.log(`b / a = ${Fr.toString(div)}`);
// Check if elements are equal
const isEqual = Fr.eq(sum, Fr.e(30));
console.log(`(a + b) === 30: ${isEqual}`);
console.log('Demonstration complete.');
}
runFieldOperations().catch(console.error);