Skip to content

Commit

Permalink
simplify internal repr of scalar
Browse files Browse the repository at this point in the history
  • Loading branch information
mitschabaude committed Apr 1, 2024
1 parent e15f77d commit 5008583
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 40 deletions.
8 changes: 4 additions & 4 deletions src/lib/ml/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,18 @@ function varToField(x: FieldVar): Field {
return Field(x);
}

function fromScalar(s: Scalar) {
return s.toConstant().constantValue;
function fromScalar(s: Scalar): ScalarConst {
return [0, s.toConstant().constantValue];
}
function toScalar(s: ScalarConst) {
return Scalar.from(s);
return Scalar.from(s[1]);
}

function fromPrivateKey(sk: PrivateKey) {
return fromScalar(sk.s);
}
function toPrivateKey(sk: ScalarConst) {
return new PrivateKey(Scalar.from(sk));
return new PrivateKey(Scalar.from(sk[1]));
}

function fromPublicKey(pk: PublicKey): MlPublicKey {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/provable/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class Group {
let g_proj = Pallas.scale(toProjective(this), scalar.toBigInt());
return fromProjective(g_proj);
} else {
let [, ...bits] = scalar.value;
let [...bits] = scalar.shiftedBits;
bits.reverse();
let [, x, y] = Snarky.group.scale(toTuple(this), [0, ...bits]);
return new Group({ x, y });
Expand Down
56 changes: 21 additions & 35 deletions src/lib/provable/scalar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,34 @@ import { Fq } from '../../bindings/crypto/finite-field.js';
import { Scalar as SignableFq } from '../../mina-signer/src/curve-bigint.js';
import { Field } from './field.js';
import { FieldVar, FieldConst } from './core/fieldvar.js';
import { MlArray } from '../ml/base.js';
import { Bool } from './bool.js';

export { Scalar, ScalarConst, unshift, shift };

// internal API
export { constantScalarToBigint };

type BoolVar = FieldVar;
type ScalarConst = [0, bigint];

const ScalarConst = {
fromBigint: constFromBigint,
toBigint: constToBigint,
is(x: any): x is ScalarConst {
return Array.isArray(x) && x[0] === 0 && typeof x[1] === 'bigint';
},
};

let scalarShift = Fq.mod(1n + 2n ** 255n);
let oneHalf = Fq.inverse(2n)!;

type ConstantScalar = Scalar & { constantValue: ScalarConst };
type ConstantScalar = Scalar & { constantValue: bigint };

/**
* Represents a {@link Scalar}.
*/
class Scalar {
value: MlArray<BoolVar>;
constantValue?: ScalarConst;
shiftedBits: FieldVar[];
constantValue?: bigint;

static ORDER = Fq.modulus;

private constructor(bits: MlArray<BoolVar>, constantValue?: bigint) {
this.value = bits;
private constructor(bits: FieldVar[], constantValue?: bigint) {
this.shiftedBits = bits;
constantValue ??= toConstantScalar(bits);
if (constantValue !== undefined) {
this.constantValue = ScalarConst.fromBigint(constantValue);
this.constantValue = constantValue;
}
}

Expand All @@ -49,10 +39,9 @@ class Scalar {
*
* If the input is too large, it is reduced modulo the scalar field size.
*/
static from(x: Scalar | ScalarConst | bigint | number | string) {
static from(x: Scalar | bigint | number | string) {
if (x instanceof Scalar) return x;
let x_ = ScalarConst.is(x) ? constToBigint(x) : x;
let scalar = Fq.mod(BigInt(x_));
let scalar = Fq.mod(BigInt(x));
let bits = toBits(scalar);
return new Scalar(bits, scalar);
}
Expand All @@ -61,7 +50,7 @@ class Scalar {
* Check whether this {@link Scalar} is a hard-coded constant in the constraint system.
* If a {@link Scalar} is constructed outside provable code, it is a constant.
*/
isConstant(): this is Scalar & { constantValue: ScalarConst } {
isConstant(): this is Scalar & { constantValue: bigint } {
return this.constantValue !== undefined;
}

Expand All @@ -74,9 +63,10 @@ class Scalar {
*/
toConstant(): ConstantScalar {
if (this.constantValue !== undefined) return this as ConstantScalar;
let [, ...bits] = this.value;
let constBits = bits.map((b) => FieldVar.constant(Snarky.field.readVar(b)));
return new Scalar([0, ...constBits]) as ConstantScalar;
let constBits = this.shiftedBits.map((b) =>
FieldVar.constant(Snarky.field.readVar(b))
);
return new Scalar(constBits) as ConstantScalar;
}

/**
Expand Down Expand Up @@ -213,8 +203,7 @@ class Scalar {
* The fields are not constrained to be boolean.
*/
static toFields(x: Scalar) {
let [, ...bits] = x.value;
return bits.map((b) => new Field(b));
return x.shiftedBits.map((b) => new Field(b));
}

/**
Expand Down Expand Up @@ -260,7 +249,7 @@ class Scalar {
* Creates a data structure from an array of serialized {@link Field} elements.
*/
static fromFields(fields: Field[]): Scalar {
return new Scalar([0, ...fields.map((x) => x.value)]);
return new Scalar(fields.map((x) => x.value));
}

/**
Expand Down Expand Up @@ -326,7 +315,7 @@ function assertConstant(x: Scalar, name: string) {
return constantScalarToBigint(x, `Scalar.${name}`);
}

function toConstantScalar([, ...bits]: MlArray<BoolVar>): bigint | undefined {
function toConstantScalar(bits: FieldVar[]): bigint | undefined {
if (bits.length !== Fq.sizeInBits)
throw Error(
`Scalar: expected bits array of length ${Fq.sizeInBits}, got ${bits.length}`
Expand All @@ -341,13 +330,10 @@ function toConstantScalar([, ...bits]: MlArray<BoolVar>): bigint | undefined {
return shift(sShifted);
}

function toBits(constantValue: bigint): MlArray<BoolVar> {
return [
0,
...SignableFq.toBits(unshift(constantValue)).map((b) =>
FieldVar.constant(BigInt(b))
),
];
function toBits(constantValue: bigint): FieldVar[] {
return SignableFq.toBits(unshift(constantValue)).map((b) =>
FieldVar.constant(BigInt(b))
);
}

/**
Expand Down Expand Up @@ -377,5 +363,5 @@ function constantScalarToBigint(s: Scalar, name: string) {
`${name}() is not available in provable code.
That means it can't be called in a @method or similar environment, and there's no alternative implemented to achieve that.`
);
return ScalarConst.toBigint(s.constantValue);
return s.constantValue;
}

0 comments on commit 5008583

Please sign in to comment.