2020-03-28 21:25:06 +01:00
|
|
|
/*
|
|
|
|
Copyright 2018 0kims association.
|
|
|
|
|
|
|
|
This file is part of zksnark JavaScript library.
|
|
|
|
|
|
|
|
zksnark JavaScript library is a free software: you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License as published by the
|
|
|
|
Free Software Foundation, either version 3 of the License, or (at your option)
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
zksnark JavaScript library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2024-10-12 17:12:41 +01:00
|
|
|
import * as chai from "chai";
|
2020-03-28 21:25:06 +01:00
|
|
|
|
2020-07-07 19:21:41 +02:00
|
|
|
import * as Scalar from "../src/scalar.js";
|
|
|
|
import PolField from "../src/polfield.js";
|
|
|
|
import ZqField from "../src/f1field.js";
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
const assert = chai.assert;
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const r = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
describe("Polynomial field", () => {
|
|
|
|
it("Should compute a multiplication", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3)];
|
|
|
|
const b = [PF.F.e(1), PF.F.e(2), PF.F.e(3)];
|
2020-03-28 21:25:06 +01:00
|
|
|
const res = PF.mul(a,b);
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.eq(res, [PF.F.e(1), PF.F.e(4), PF.F.e(10), PF.F.e(12), PF.F.e(9)]));
|
2020-03-28 21:25:06 +01:00
|
|
|
});
|
|
|
|
it("Should compute a multiplication 2", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(5), PF.F.e(1)];
|
|
|
|
const b = [PF.F.e(-5), PF.F.e(1)];
|
2020-03-28 21:25:06 +01:00
|
|
|
const res = PF.mul(a,b);
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.eq(res, [PF.F.e(-25), PF.F.e(0), PF.F.e(1)]));
|
2020-03-28 21:25:06 +01:00
|
|
|
});
|
|
|
|
it("Should compute an addition", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(5), PF.F.e(1)];
|
|
|
|
const b = [PF.F.e(-5), PF.F.e(1)];
|
2020-03-28 21:25:06 +01:00
|
|
|
const res = PF.add(a,b);
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.eq(res, [PF.F.e(0), PF.F.e(2)]));
|
2020-03-28 21:25:06 +01:00
|
|
|
});
|
|
|
|
it("Should compute a substraction", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(5), PF.F.e(3), PF.F.e(4)];
|
|
|
|
const b = [PF.F.e(5), PF.F.e(1)];
|
2020-03-28 21:25:06 +01:00
|
|
|
const res = PF.sub(a,b);
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.eq(res, [PF.F.e(0), PF.F.e(2), PF.F.e(4)]));
|
2020-03-28 21:25:06 +01:00
|
|
|
});
|
|
|
|
it("Should compute reciprocal", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = PF.normalize([PF.F.e(4), PF.F.e(1), PF.F.e(-3), PF.F.e(-1), PF.F.e(2),PF.F.e(1), PF.F.e(-1), PF.F.e(1)]);
|
2020-03-28 21:25:06 +01:00
|
|
|
const res = PF._reciprocal(a, 3, 0);
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.eq(res, PF.normalize([PF.F.e(12), PF.F.e(15), PF.F.e(3), PF.F.e(-4), PF.F.e(-3), PF.F.e(0), PF.F.e(1), PF.F.e(1)])));
|
2020-03-28 21:25:06 +01:00
|
|
|
});
|
|
|
|
it("Should div2", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
|
|
|
// x^6
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(0),PF.F.e(0), PF.F.e(1)];
|
2020-03-28 21:25:06 +01:00
|
|
|
// x^5
|
2020-04-18 20:07:29 +02:00
|
|
|
const b = [PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(1)];
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
const res = PF._div2(6, b);
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.eq(res, [PF.F.e(0), PF.F.e(1)]));
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
const res2 = PF.div(a,b);
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.eq(res2, [PF.F.e(0), PF.F.e(1)]));
|
2020-03-28 21:25:06 +01:00
|
|
|
});
|
|
|
|
it("Should div", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3), PF.F.e(4), PF.F.e(5),PF.F.e(6), PF.F.e(7)];
|
|
|
|
const b = [PF.F.e(8), PF.F.e(9), PF.F.e(10), PF.F.e(11), PF.F.e(12), PF.F.e(13)];
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
const c = PF.mul(a,b);
|
|
|
|
const d = PF.div(c,b);
|
|
|
|
|
|
|
|
assert(PF.eq(a, d));
|
|
|
|
});
|
|
|
|
it("Should div big/small", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3), PF.F.e(4), PF.F.e(5),PF.F.e(6), PF.F.e(7)];
|
|
|
|
const b = [PF.F.e(8), PF.F.e(9)];
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
const c = PF.mul(a,b);
|
|
|
|
const d = PF.div(c,b);
|
|
|
|
|
|
|
|
assert(PF.eq(a, d));
|
|
|
|
});
|
|
|
|
it("Should div random big", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
|
|
|
let a = [];
|
|
|
|
let b = [];
|
2020-04-18 20:07:29 +02:00
|
|
|
for (let i=0; i<1000; i++) a.push(PF.F.e(Math.floor(Math.random()*100000) -500000));
|
|
|
|
for (let i=0; i<900; i++) b.push(PF.F.e(Math.floor(Math.random()*100000) -500000));
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
a = PF.normalize(a);
|
|
|
|
b = PF.normalize(a);
|
|
|
|
|
|
|
|
const c = PF.mul(a,b);
|
|
|
|
|
|
|
|
const d = PF.div(c,b);
|
|
|
|
|
|
|
|
assert(PF.eq(a, d));
|
|
|
|
}).timeout(10000);
|
|
|
|
it("Should evaluate and zero", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
2020-04-18 20:07:29 +02:00
|
|
|
const p = [PF.F.neg(PF.F.e(2)), PF.F.e(1)];
|
2022-03-26 10:45:27 -07:00
|
|
|
const v = PF.evaluate(p, PF.F.e(2));
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.F.eq(v, PF.F.e(0)));
|
2020-03-28 21:25:06 +01:00
|
|
|
});
|
|
|
|
it("Should evaluate bigger number", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
2020-04-18 20:07:29 +02:00
|
|
|
const p = [PF.F.e(1), PF.F.e(2), PF.F.e(3)];
|
2022-03-26 10:45:27 -07:00
|
|
|
const v = PF.evaluate(p, PF.F.e(2));
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.F.eq(v, PF.F.e(17)));
|
2020-03-28 21:25:06 +01:00
|
|
|
});
|
|
|
|
it("Should create lagrange polynomial minmal", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
|
|
|
const points=[];
|
2020-04-18 20:07:29 +02:00
|
|
|
points.push([PF.F.e(1), PF.F.e(1)]);
|
|
|
|
points.push([PF.F.e(2), PF.F.e(2)]);
|
|
|
|
points.push([PF.F.e(3), PF.F.e(5)]);
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
const p=PF.lagrange(points);
|
|
|
|
|
|
|
|
for (let i=0; i<points.length; i++) {
|
2022-03-26 10:45:27 -07:00
|
|
|
const v = PF.evaluate(p, points[i][0]);
|
2020-03-28 21:25:06 +01:00
|
|
|
assert(PF.F.eq(v, points[i][1]));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
it("Should create lagrange polynomial", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
|
|
|
|
const points=[];
|
2020-04-18 20:07:29 +02:00
|
|
|
points.push([PF.F.e(1), PF.F.e(2)]);
|
|
|
|
points.push([PF.F.e(2), PF.F.e(-2)]);
|
|
|
|
points.push([PF.F.e(3), PF.F.e(0)]);
|
|
|
|
points.push([PF.F.e(4), PF.F.e(453345)]);
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
const p=PF.lagrange(points);
|
|
|
|
|
|
|
|
for (let i=0; i<points.length; i++) {
|
2022-03-26 10:45:27 -07:00
|
|
|
const v = PF.evaluate(p, points[i][0]);
|
2020-03-28 21:25:06 +01:00
|
|
|
assert(PF.F.eq(v, points[i][1]));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
it("Should test ruffini", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3), PF.F.e(4), PF.F.e(5),PF.F.e(6), PF.F.e(7)];
|
2020-03-28 21:25:06 +01:00
|
|
|
|
2020-04-18 20:07:29 +02:00
|
|
|
const b = PF.mul(a, [PF.F.e(-7), PF.F.e(1)]);
|
|
|
|
const c = PF.ruffini(b, PF.F.e(7));
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
assert(PF.eq(a, c));
|
|
|
|
});
|
|
|
|
it("Should test roots", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
|
|
|
let rt;
|
|
|
|
|
|
|
|
|
|
|
|
rt = PF.oneRoot(256, 16);
|
|
|
|
for (let i=0; i<8; i++) {
|
|
|
|
rt = PF.F.mul(rt, rt);
|
|
|
|
}
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.F.eq(rt, PF.F.one));
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
rt = PF.oneRoot(256, 15);
|
|
|
|
for (let i=0; i<8; i++) {
|
|
|
|
rt = PF.F.mul(rt, rt);
|
|
|
|
}
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.F.eq(rt, PF.F.one));
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
rt = PF.oneRoot(8, 3);
|
|
|
|
for (let i=0; i<3; i++) {
|
|
|
|
rt = PF.F.mul(rt, rt);
|
|
|
|
}
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.F.eq(rt, PF.F.one));
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
rt = PF.oneRoot(8, 0);
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.F.eq(rt, PF.F.one));
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
});
|
|
|
|
it("Should create a polynomial with values at roots with fft", () => {
|
|
|
|
const PF = new PolField(new ZqField(r));
|
2020-04-18 20:07:29 +02:00
|
|
|
const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3), PF.F.e(4), PF.F.e(5),PF.F.e(6), PF.F.e(7)];
|
2020-03-28 21:25:06 +01:00
|
|
|
|
|
|
|
const p = PF.ifft(a);
|
|
|
|
|
|
|
|
for (let i=0; i<a.length; i++) {
|
2022-03-26 10:45:27 -07:00
|
|
|
const s = PF.evaluate(p, PF.oneRoot(8,i));
|
2020-04-18 20:07:29 +02:00
|
|
|
assert(PF.F.eq(s, a[i]));
|
2020-03-28 21:25:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|