org.ethereum.crypto.zksnark.Fp2 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ethereumj-core Show documentation
Show all versions of ethereumj-core Show documentation
Java implementation of the Ethereum protocol adapted to use for Hedera Smart Contract Service
The newest version!
/*
* Copyright (c) [2016] [ ]
* This file is part of the ethereumJ library.
*
* The ethereumJ library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The ethereumJ 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the ethereumJ library. If not, see .
*/
package org.ethereum.crypto.zksnark;
import java.math.BigInteger;
/**
* Arithmetic in F_p2
*
*
* "p" equals 21888242871839275222246405745257275088696311157297823662689037894645226208583,
* elements of F_p2 are represented as a polynomials "a * i + b" modulo "i^2 + 1" from the ring F_p[i]
*
*
* Field arithmetic is ported from libff
*
* @author Mikhail Kalinin
* @since 01.09.2017
*/
class Fp2 implements Field {
static final Fp2 ZERO = new Fp2(Fp.ZERO, Fp.ZERO);
static final Fp2 _1 = new Fp2(Fp._1, Fp.ZERO);
static final Fp2 NON_RESIDUE = new Fp2(BigInteger.valueOf(9), BigInteger.ONE);
static final Fp[] FROBENIUS_COEFFS_B = new Fp[] {
new Fp(BigInteger.ONE),
new Fp(new BigInteger("21888242871839275222246405745257275088696311157297823662689037894645226208582"))
};
Fp a;
Fp b;
Fp2(Fp a, Fp b) {
this.a = a;
this.b = b;
}
Fp2(BigInteger a, BigInteger b) {
this(new Fp(a), new Fp(b));
}
@Override
public Fp2 squared() {
// using Complex squaring
Fp ab = a.mul(b);
Fp ra = a.add(b).mul(b.mul(Fp.NON_RESIDUE).add(a))
.sub(ab).sub(ab.mul(Fp.NON_RESIDUE)); // ra = (a + b)(a + NON_RESIDUE * b) - ab - NON_RESIDUE * b
Fp rb = ab.dbl();
return new Fp2(ra, rb);
}
@Override
public Fp2 mul(Fp2 o) {
Fp aa = a.mul(o.a);
Fp bb = b.mul(o.b);
Fp ra = bb.mul(Fp.NON_RESIDUE).add(aa); // ra = a1 * a2 + NON_RESIDUE * b1 * b2
Fp rb = a.add(b).mul(o.a.add(o.b)).sub(aa).sub(bb); // rb = (a1 + b1)(a2 + b2) - a1 * a2 - b1 * b2
return new Fp2(ra, rb);
}
@Override
public Fp2 add(Fp2 o) {
return new Fp2(a.add(o.a), b.add(o.b));
}
@Override
public Fp2 sub(Fp2 o) {
return new Fp2(a.sub(o.a), b.sub(o.b));
}
@Override
public Fp2 dbl() {
return this.add(this);
}
@Override
public Fp2 inverse() {
Fp t0 = a.squared();
Fp t1 = b.squared();
Fp t2 = t0.sub(Fp.NON_RESIDUE.mul(t1));
Fp t3 = t2.inverse();
Fp ra = a.mul(t3); // ra = a * t3
Fp rb = b.mul(t3).negate(); // rb = -(b * t3)
return new Fp2(ra, rb);
}
@Override
public Fp2 negate() {
return new Fp2(a.negate(), b.negate());
}
@Override
public boolean isZero() {
return this.equals(ZERO);
}
@Override
public boolean isValid() {
return a.isValid() && b.isValid();
}
static Fp2 create(BigInteger aa, BigInteger bb) {
Fp a = Fp.create(aa);
Fp b = Fp.create(bb);
return new Fp2(a, b);
}
static Fp2 create(byte[] aa, byte[] bb) {
Fp a = Fp.create(aa);
Fp b = Fp.create(bb);
return new Fp2(a, b);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Fp2 fp2 = (Fp2) o;
if (a != null ? !a.equals(fp2.a) : fp2.a != null) return false;
return !(b != null ? !b.equals(fp2.b) : fp2.b != null);
}
Fp2 frobeniusMap(int power) {
Fp ra = a;
Fp rb = FROBENIUS_COEFFS_B[power % 2].mul(b);
return new Fp2(ra, rb);
}
Fp2 mulByNonResidue() {
return NON_RESIDUE.mul(this);
}
@Override
public String toString() {
return String.format("%si + %s", a.toString(), b.toString());
}
}