Represent elements from field F_{p^2} as `real + i * imag`

Reason: Circom and Ethereum EIP-197 both represent these
elements as arrays of two elements, but they do it in
reverse order of each other. This change makes it explicit
which number is the real part, and which number is the
imaginary part.
This commit is contained in:
Mark Spanbroek 2024-02-20 17:16:49 +01:00 committed by markspanbroek
parent ed54b80fc9
commit f413f1ea64
4 changed files with 20 additions and 12 deletions

View File

@ -6,9 +6,17 @@ struct G1Point {
uint y;
}
// A field element F_{p^2} encoded as `real + i * imag`.
// We chose to not represent this as an array of 2 numbers, because both Circom
// and Ethereum EIP-197 encode to an array, but with conflicting encodings.
struct Fp2Element {
uint real;
uint imag;
}
struct G2Point {
uint[2] x;
uint[2] y;
Fp2Element x;
Fp2Element y;
}
struct Groth16Proof {

View File

@ -92,10 +92,10 @@ library Pairing {
for (uint i = 0; i < elements; i++) {
input[i * 6 + 0] = p1[i].x;
input[i * 6 + 1] = p1[i].y;
input[i * 6 + 2] = p2[i].x[0];
input[i * 6 + 3] = p2[i].x[1];
input[i * 6 + 4] = p2[i].y[0];
input[i * 6 + 5] = p2[i].y[1];
input[i * 6 + 2] = p2[i].x.imag;
input[i * 6 + 3] = p2[i].x.real;
input[i * 6 + 4] = p2[i].y.imag;
input[i * 6 + 5] = p2[i].y.real;
}
uint[1] memory out;
bool success;

View File

@ -12,10 +12,10 @@ contract TestVerifier is IGroth16Verifier {
return
!(proof.a.x == 0 &&
proof.a.y == 0 &&
proof.b.x[0] == 0 &&
proof.b.x[1] == 0 &&
proof.b.y[0] == 0 &&
proof.b.y[1] == 0 &&
proof.b.x.real == 0 &&
proof.b.x.imag == 0 &&
proof.b.y.real == 0 &&
proof.b.y.imag == 0 &&
proof.c.x == 0 &&
proof.c.y == 0);
}

View File

@ -16,8 +16,8 @@ function G1ToStruct(point) {
function G2ToStruct(point) {
return {
x: [point[0][1], point[0][0]],
y: [point[1][1], point[1][0]],
x: { real: point[0][0], imag: point[0][1] },
y: { real: point[1][0], imag: point[1][1] },
}
}