Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foreign curve and ECDSA #1007

Merged
merged 113 commits into from
Dec 12, 2023
Merged
Changes from 1 commit
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
a637e7c
fix example
mitschabaude Jun 28, 2023
1febfbe
initial minimal foreign curve, doesn't work yet
mitschabaude Jun 28, 2023
e012ba6
initial work on test
mitschabaude Jun 28, 2023
addf84c
working bare bones ec with add
mitschabaude Jun 29, 2023
578f444
make curve provable
mitschabaude Jun 29, 2023
4fb98e6
expose common ec methods
mitschabaude Jun 29, 2023
7a228c3
add remaining provable methods
mitschabaude Jun 29, 2023
e241042
correct comments
mitschabaude Jun 29, 2023
6f0a888
minor tweaks
mitschabaude Jun 30, 2023
44779a1
improve api
mitschabaude Jun 30, 2023
26affb1
stub out ecdsa factory
mitschabaude Jun 30, 2023
81b9118
expose ecdsa methods
mitschabaude Jun 30, 2023
1dae1dc
from hex
mitschabaude Jun 30, 2023
005a2aa
start writing test for eth signature
mitschabaude Jun 30, 2023
b237f9c
ecdsa test
mitschabaude Jun 30, 2023
36ad895
minor
mitschabaude Jul 5, 2023
f4e59b2
Merge branch 'feature/foreign-field' into feature/ecdsa
mitschabaude Jul 12, 2023
9b5cf28
bindings
mitschabaude Jul 12, 2023
b530803
renamings
mitschabaude Jul 12, 2023
afce065
add most constant curve impls
mitschabaude Jul 13, 2023
6b43f92
scale
mitschabaude Jul 13, 2023
5781049
constant subgroup check
mitschabaude Jul 13, 2023
5ad6b49
getting non provable curve ops to run
mitschabaude Jul 13, 2023
78c635b
start writing doc comments
mitschabaude Jul 13, 2023
bf9968a
more doc comments, unsafe parameter, proper check()
mitschabaude Jul 13, 2023
61bb485
fox typo and foreign curve check
mitschabaude Jul 13, 2023
499928d
ecdsa doc comments
mitschabaude Jul 13, 2023
f2460f1
implement ecdsa in ts for non-provable
mitschabaude Jul 13, 2023
07a45f7
minor
mitschabaude Jul 13, 2023
6c01efe
subgroup check in constant verification
mitschabaude Jul 13, 2023
2dce057
web compatible benchmark
mitschabaude Jul 13, 2023
3437479
foreign field benchmark
mitschabaude Jul 14, 2023
c033828
Merge branch 'feature/foreign-field' into feature/ecdsa
mitschabaude Nov 30, 2023
45fb41f
Merge branch 'feature/ecdsa-new' into feature/ecdsa
mitschabaude Nov 30, 2023
616e47a
Merge branch 'main' into feature/ecdsa
mitschabaude Nov 30, 2023
5384087
make foreign field struct-friendly
mitschabaude Nov 30, 2023
b9205c4
bindings
mitschabaude Nov 30, 2023
c6989dd
fix foreign curve compilation except the class return
mitschabaude Nov 30, 2023
321fca0
fixup foreign field
mitschabaude Nov 30, 2023
8459851
delete duplicate curve params
mitschabaude Nov 30, 2023
56795cf
foreign field: remove duplicate private method
mitschabaude Nov 30, 2023
bb61f3d
remove private
mitschabaude Nov 30, 2023
c0d8867
compiles
mitschabaude Nov 30, 2023
c85c5ea
tests compile
mitschabaude Nov 30, 2023
6385b9a
Merge branch 'feature/foreign-field' into feature/ecdsa
mitschabaude Nov 30, 2023
d9353d4
remove unnecessary helper
mitschabaude Dec 1, 2023
6f3413a
bindings
mitschabaude Dec 1, 2023
e9d17de
move foreign curve class outside class factory
mitschabaude Dec 1, 2023
13081cc
minor
mitschabaude Dec 1, 2023
190f3e3
negate
mitschabaude Dec 1, 2023
8c09689
support message in foreign field assertMul
mitschabaude Dec 1, 2023
cd9193e
assert on curve
mitschabaude Dec 1, 2023
722cfd6
scale gadget
mitschabaude Dec 1, 2023
a7fc887
Merge branch 'feature/foreign-field' into feature/ecdsa
mitschabaude Dec 4, 2023
e1fa376
Merge branch 'feature/ecdsa-new' into feature/ecdsa
mitschabaude Dec 4, 2023
da21b19
fixup merge
mitschabaude Dec 4, 2023
132d879
support a!=0 in assert on curve
mitschabaude Dec 4, 2023
d953a70
implement subgroup check
mitschabaude Dec 4, 2023
d7707dc
fix assert on curve
mitschabaude Dec 4, 2023
ec7131e
not so slow anymore
mitschabaude Dec 4, 2023
1f7e291
expose cs summary
mitschabaude Dec 4, 2023
0122785
delete bad example
mitschabaude Dec 4, 2023
4b5af0b
remove curve parameter limitations from foreign curve class
mitschabaude Dec 4, 2023
e1282d1
cleanup comments, move redundant unit test to example
mitschabaude Dec 4, 2023
1348779
examples fixup
mitschabaude Dec 4, 2023
6100817
make ecdsa class work
mitschabaude Dec 4, 2023
ecdeea7
move ecdsa class outside factory
mitschabaude Dec 4, 2023
9fe6e59
bindings
mitschabaude Dec 4, 2023
6290202
make type pure
mitschabaude Dec 4, 2023
9dea77f
add ForeignField.random()
mitschabaude Dec 4, 2023
a3577b0
add Ecdsa.sign()
mitschabaude Dec 4, 2023
b35cc61
rewrite ecdsa example using high level API
mitschabaude Dec 4, 2023
5095fac
fix constraint system test flakiness
mitschabaude Dec 4, 2023
6ce500e
Merge branch 'feature/ecdsa-new' into feature/ecdsa
mitschabaude Dec 4, 2023
3e2990c
collateral damage from using higher-level API
mitschabaude Dec 4, 2023
e4ffb48
Merge branch 'feature/ecdsa-new' into feature/ecdsa
mitschabaude Dec 4, 2023
e9c21b0
update benchmark
mitschabaude Dec 4, 2023
a668916
move ecdsa example to where it makes more sense
mitschabaude Dec 4, 2023
8cc376f
doccomment tweaks
mitschabaude Dec 4, 2023
4333762
revert unnecessary change
mitschabaude Dec 4, 2023
c6c39cc
save constraints
mitschabaude Dec 4, 2023
9590840
add ec gadgets
mitschabaude Dec 4, 2023
49b98c5
adapt constant case in multiscalarmul, remove the one in scale
mitschabaude Dec 4, 2023
cbd335f
remove testing code
mitschabaude Dec 4, 2023
9ebd5f3
start writing ec gadgets tests
mitschabaude Dec 4, 2023
07a1fde
simplify build scripts
mitschabaude Dec 5, 2023
502a497
equivalent: add verbose option and onlyif combinator
mitschabaude Dec 5, 2023
578a8ad
fix ec test
mitschabaude Dec 5, 2023
a7f997b
add assert on curve
mitschabaude Dec 5, 2023
7e83c43
minor
mitschabaude Dec 5, 2023
43eadf7
minor console formatting
mitschabaude Dec 5, 2023
78e0c63
standardize ec gadgets inputs
mitschabaude Dec 5, 2023
d32ad75
make record forward provable
mitschabaude Dec 5, 2023
24d3a32
add missing label
mitschabaude Dec 5, 2023
c07857f
verbose ecdsa test
mitschabaude Dec 5, 2023
80d10a6
catch missing provable
mitschabaude Dec 5, 2023
d29a9b5
fix ecdsa unit test
mitschabaude Dec 5, 2023
40cb374
remove use of build:node
mitschabaude Dec 5, 2023
ce82667
remove use of build:node
mitschabaude Dec 5, 2023
81d0047
improve comments
mitschabaude Dec 5, 2023
818046c
flesh out doccomments
mitschabaude Dec 5, 2023
3d14a4e
move dangerous foreign field equals
mitschabaude Dec 5, 2023
dfc7e97
change to safe equals() methods in foreign field, rename assertCanonical
mitschabaude Dec 5, 2023
0403912
add safe ec addition
mitschabaude Dec 5, 2023
abe4d56
signature to bigint
mitschabaude Dec 5, 2023
3a3cce3
adapt unit test
mitschabaude Dec 5, 2023
9bcb6fd
delete ec and ecdsa gadgets namespaces
mitschabaude Dec 5, 2023
31282ea
changelog
mitschabaude Dec 5, 2023
db8f63a
Revert "remove ecdsa from vk test for now"
mitschabaude Dec 6, 2023
120ae94
Merge branch 'tmp' into feature/ecdsa
mitschabaude Dec 6, 2023
0a96141
Merge branch 'main' into feature/ecdsa
mitschabaude Dec 7, 2023
62091b8
dump vks
mitschabaude Dec 7, 2023
5430dc4
Merge branch 'main' into feature/ecdsa
mitschabaude Dec 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 86 additions & 21 deletions src/lib/foreign-curve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ type ForeignCurveClass = ReturnType<typeof createForeignCurve>;
* @param options
* - `unsafe: boolean` determines whether `ForeignField` elements are constrained to be valid on creation.
*/
function createForeignCurve(curve: CurveParams) {
function createForeignCurve(curve: CurveParams, { unsafe = false } = {}) {
const curveParamsMl = Snarky.foreignCurve.create(MlCurveParams(curve));
const curveName = curve.name;
const hasCofactor = curve.cofactor !== undefined && curve.cofactor !== 1n;

class BaseField extends createForeignField(curve.modulus) {}
class ScalarField extends createForeignField(curve.order) {}
class BaseField extends createForeignField(curve.modulus, { unsafe }) {}
class ScalarField extends createForeignField(curve.order, { unsafe }) {}

// this is necessary to simplify the type of ForeignCurve, to avoid
// TS7056: The inferred type of this node exceeds the maximum length the compiler will serialize.
Expand All @@ -81,8 +82,11 @@ function createForeignCurve(curve: CurveParams) {
generator: curve.gen,
});

function toConstant(x: ForeignCurve) {
return { ...x.toBigint(), infinity: false };
function toBigint(g: Affine) {
return { x: g.x.toBigInt(), y: g.y.toBigInt() };
}
function toConstant(g: Affine) {
return { ...toBigint(g), infinity: false };
}

class ForeignCurve extends Affine {
Expand Down Expand Up @@ -117,6 +121,9 @@ function createForeignCurve(curve: CurveParams) {
if (this.isConstant()) this.assertOnCurve();
}

/**
* Coerce the input to a {@link ForeignCurve}.
*/
static from(
g:
| ForeignCurve
Expand All @@ -128,6 +135,9 @@ function createForeignCurve(curve: CurveParams) {

static #curveParamsMlVar: unknown | undefined;

/**
* Initialize usage of the curve. This function has to be called oncel per provable method to use the curve.
mitschabaude marked this conversation as resolved.
Show resolved Hide resolved
*/
static initialize() {
if (!inCheckedComputation()) return;
ForeignCurve.#curveParamsMlVar =
Expand All @@ -145,14 +155,25 @@ function createForeignCurve(curve: CurveParams) {

static generator = new ForeignCurve(curve.gen);

/**
* Checks whether this curve point is constant.
*
* See {@link FieldVar} to understand constants vs variables.
*/
isConstant() {
return isConstant(ForeignCurve, this);
}

/**
* Convert this curve point to a point with bigint coordinates.
*/
toBigint() {
return { x: this.x.toBigInt(), y: this.y.toBigInt() };
}

/**
* Elliptic curve addition.
*/
add(
h:
| ForeignCurve
Expand All @@ -168,6 +189,9 @@ function createForeignCurve(curve: CurveParams) {
return new ForeignCurve(p);
}

/**
* Elliptic curve doubling.
*/
double() {
if (this.isConstant()) {
let z = ConstantCurve.double(toConstant(this));
Expand All @@ -178,6 +202,9 @@ function createForeignCurve(curve: CurveParams) {
return new ForeignCurve(p);
}

/**
* Elliptic curve negation.
*/
negate() {
if (this.isConstant()) {
let z = ConstantCurve.negate(toConstant(this));
Expand All @@ -188,24 +215,34 @@ function createForeignCurve(curve: CurveParams) {
return new ForeignCurve(p);
}

assertOnCurve() {
if (this.isConstant()) {
let isOnCurve = ConstantCurve.isOnCurve(toConstant(this));
static #assertOnCurve(g: Affine) {
if (isConstant(ForeignCurve, g)) {
let isOnCurve = ConstantCurve.isOnCurve(toConstant(g));
if (!isOnCurve)
throw Error(
`${this.constructor.name}.assertOnCurve(): ${JSON.stringify(
ForeignCurve.toJSON(this)
`${this.name}.assertOnCurve(): ${JSON.stringify(
ForeignCurve.toJSON(g)
)} is not on the curve.`
);
return;
}
let curve = ForeignCurve._getParams(
`${this.constructor.name}.assertOnCurve`
);
Snarky.foreignCurve.assertOnCurve(toMl(this), curve);
let curve = ForeignCurve._getParams(`${this.name}.assertOnCurve`);
Snarky.foreignCurve.assertOnCurve(toMl(g), curve);
}

/**
* Assert that this point lies on the elliptic curve, which means it satisfies the equation
* y^2 = x^3 + ax + b
*/
assertOnCurve() {
ForeignCurve.#assertOnCurve(this);
}

// TODO wrap this in a `Scalar` type which is a Bool array under the hood?
/**
* Elliptic curve scalar multiplication, where the scalar is represented as a little-endian
* array of bits, and each bit is represented by a {@link Bool}.
*/
scale(scalar: Bool[]) {
if (this.isConstant() && scalar.every((b) => b.isConstant())) {
let scalar0 = scalar.map((b) => b.toBoolean());
Expand All @@ -221,19 +258,41 @@ function createForeignCurve(curve: CurveParams) {
return new ForeignCurve(p);
}

assertInSubgroup() {
if (this.isConstant()) {
let isInGroup = ConstantCurve.isInSubgroup(toConstant(this));
static #assertInSubgroup(g: Affine) {
if (isConstant(Affine, g)) {
let isInGroup = ConstantCurve.isInSubgroup(toConstant(g));
if (!isInGroup)
throw Error(
`${this.constructor.name}.assertInSubgroup(): ${JSON.stringify(
this
`${this.name}.assertInSubgroup(): ${JSON.stringify(
g
)} is not in the target subgroup.`
);
return;
}
let curve = ForeignCurve._getParams(`${curveName}.assertInSubgroup`);
Snarky.foreignCurve.checkSubgroup(toMl(this), curve);
let curve_ = ForeignCurve._getParams(`${curveName}.assertInSubgroup`);
Snarky.foreignCurve.checkSubgroup(toMl(g), curve_);
}

/**
* Assert than this point lies in the subgroup defined by order*P = 0,
* by performing the scalar multiplication.
*/
assertInSubgroup() {
ForeignCurve.#assertInSubgroup(this);
}

/**
* Check that this is a valid element of the target subgroup of the curve:
* - Use {@link assertOnCurve()} to check that the point lies on the curve
* - If the curve has cofactor unequal to 1, use {@link assertInSubgroup()}.
*
* **Exception**: If {@link createForeignCurve} is called with `{ unsafe: true }`,
* we don't check that curve elements are valid by default.
*/
static check(g: Affine) {
if (unsafe) return;
ForeignCurve.#assertOnCurve(g);
if (hasCofactor) ForeignCurve.#assertInSubgroup(g);
}

static BaseField = BaseField;
Expand All @@ -260,6 +319,12 @@ type CurveParams = {
* Scalar field modulus = group order
*/
order: bigint;
/**
* Cofactor = size of EC / order
*
* This can be left undefined if the cofactor is 1.
*/
cofactor?: bigint;
/**
* The `a` parameter in the curve equation y^2 = x^3 + ax + b
*/
Expand Down