ox
Version:
Ethereum Standard Library
122 lines • 3.91 kB
JavaScript
import { bls12_381 as bls } from '@noble/curves/bls12-381.js';
import * as Errors from './Errors.js';
import * as Hex from './Hex.js';
const FP_SIZE = 48;
/** @internal */
export function fpToBigInt(value) {
return BigInt(value);
}
/** @internal */
export function fpFromBigInt(value) {
return Hex.fromNumber(value, { size: FP_SIZE });
}
/** @internal */
export function fp2ToBigInt(value) {
return { c0: BigInt(value.c0), c1: BigInt(value.c1) };
}
/** @internal */
export function fp2FromBigInt(value) {
return {
c0: Hex.fromNumber(value.c0, { size: FP_SIZE }),
c1: Hex.fromNumber(value.c1, { size: FP_SIZE }),
};
}
/**
* Converts a structured {@link ox#BlsPoint.BlsPoint} into a noble/curves
* `Point` instance for the appropriate group (G1 or G2).
*
* @internal
*/
export function toNoblePoint(point, group) {
if (group === 'G1') {
const p = point;
return new bls.G1.Point(fpToBigInt(p.x), fpToBigInt(p.y), fpToBigInt(p.z));
}
const p = point;
// noble's G2.Point ctor accepts Fp2 instances. Construct via the field
// helper so we get a real `Fp2` rather than a plain `{c0, c1}`.
const Fp2 = bls.fields.Fp2;
const x = Fp2.create
? Fp2.create(fp2ToBigInt(p.x))
: Fp2.fromBigTuple([BigInt(p.x.c0), BigInt(p.x.c1)]);
const y = Fp2.create
? Fp2.create(fp2ToBigInt(p.y))
: Fp2.fromBigTuple([BigInt(p.y.c0), BigInt(p.y.c1)]);
const z = Fp2.create
? Fp2.create(fp2ToBigInt(p.z))
: Fp2.fromBigTuple([BigInt(p.z.c0), BigInt(p.z.c1)]);
return new bls.G2.Point(x, y, z);
}
/**
* Converts a noble/curves `Point` into a structured
* {@link ox#BlsPoint.BlsPoint}.
*
* @internal
*/
export function fromNoblePoint(point, group) {
if (group === 'G1') {
return {
x: fpFromBigInt(point.X),
y: fpFromBigInt(point.Y),
z: fpFromBigInt(point.Z),
};
}
// G2: `point.X/Y/Z` are Fp2 instances exposing `.c0` / `.c1` bigints.
return {
x: { c0: fpFromBigInt(point.X.c0), c1: fpFromBigInt(point.X.c1) },
y: { c0: fpFromBigInt(point.Y.c0), c1: fpFromBigInt(point.Y.c1) },
z: { c0: fpFromBigInt(point.Z.c0), c1: fpFromBigInt(point.Z.c1) },
};
}
/**
* Converts a BLS point to {@link ox#Bytes.Bytes}.
*
* @example
* ### Public Key to Bytes
* ```ts twoslash
* import { Bls, BlsPoint } from 'ox'
*
* const publicKey = Bls.getPublicKey({ privateKey: '0x...' })
* const publicKeyBytes = BlsPoint.toBytes(publicKey)
* // @log: Uint8Array [172, 175, 255, ...]
* ```
*
* @example
* ### Signature to Bytes
* ```ts twoslash
* import { Bls, BlsPoint } from 'ox'
*
* const signature = Bls.sign({
* payload: '0x...',
* privateKey: '0x...'
* })
* const signatureBytes = BlsPoint.toBytes(signature)
* // @log: Uint8Array [172, 175, 255, ...]
* ```
*
* @param point - The BLS point to convert.
* @returns The bytes representation of the BLS point.
*/
export function toBytes(point) {
const isG1 = typeof point.z === 'string';
const noblePoint = toNoblePoint(point, isG1 ? 'G1' : 'G2');
return noblePoint.toBytes();
}
// eslint-disable-next-line jsdoc-js/require-jsdoc
export function toHex(point) {
return Hex.fromBytes(toBytes(point));
}
// eslint-disable-next-line jsdoc-js/require-jsdoc
export function fromBytes(bytes, group) {
const expectedLength = group === 'G1' ? 48 : 96;
if (bytes.length !== expectedLength)
throw new Errors.BaseError(`Expected ${expectedLength} bytes for a ${group} point, received ${bytes.length}.`);
const Group = group === 'G1' ? bls.G1 : bls.G2;
const point = Group.Point.fromBytes(bytes);
return fromNoblePoint(point, group);
}
// eslint-disable-next-line jsdoc-js/require-jsdoc
export function fromHex(hex, group) {
return fromBytes(Hex.toBytes(hex), group);
}
//# sourceMappingURL=BlsPoint.js.map