Prad Nukala 807b2e86ec
feature/1220 origin handle exists method (#1241)
* feat: add docs and CI workflow for publishing to onsonr.dev

* (refactor): Move hway,motr executables to their own repos

* feat: simplify devnet and testnet configurations

* refactor: update import path for didcrypto package

* docs(networks): Add README with project overview, architecture, and community links

* refactor: Move network configurations to deploy directory

* build: update golang version to 1.23

* refactor: move logger interface to appropriate package

* refactor: Move devnet configuration to networks/devnet

* chore: improve release process with date variable

* (chore): Move Crypto Library

* refactor: improve code structure and readability in DID module

* feat: integrate Trunk CI checks

* ci: optimize CI workflow by removing redundant build jobs

---------

Co-authored-by: Darp Alakun <i@prad.nu>
2025-01-06 17:06:10 +00:00

255 lines
4.9 KiB
Go
Executable File

package bls12381
const coefficientsG2 = 68
type Engine struct {
pairs []pair
}
type pair struct {
g1 G1
g2 G2
}
type g2Prepared struct {
identity int
coefficients []coefficients
}
type coefficients struct {
a, b, c fp2
}
func (c *coefficients) CMove(arg1, arg2 *coefficients, choice int) *coefficients {
c.a.CMove(&arg1.a, &arg2.a, choice)
c.b.CMove(&arg1.b, &arg2.b, choice)
c.c.CMove(&arg1.c, &arg2.c, choice)
return c
}
// AddPair adds a pair of points to be paired
func (e *Engine) AddPair(g1 *G1, g2 *G2) *Engine {
var p pair
p.g1.ToAffine(g1)
p.g2.ToAffine(g2)
if p.g1.IsIdentity()|p.g2.IsIdentity() == 0 {
e.pairs = append(e.pairs, p)
}
return e
}
// AddPairInvG1 adds a pair of points to be paired. G1 point is negated
func (e *Engine) AddPairInvG1(g1 *G1, g2 *G2) *Engine {
var p G1
p.Neg(g1)
return e.AddPair(&p, g2)
}
// AddPairInvG2 adds a pair of points to be paired. G2 point is negated
func (e *Engine) AddPairInvG2(g1 *G1, g2 *G2) *Engine {
var p G2
p.Neg(g2)
return e.AddPair(g1, &p)
}
func (e *Engine) Reset() *Engine {
e.pairs = []pair{}
return e
}
func (e *Engine) Check() bool {
return e.pairing().IsOne() == 1
}
func (e *Engine) Result() *Gt {
return e.pairing()
}
func (e *Engine) pairing() *Gt {
f := new(Gt).SetOne()
if len(e.pairs) == 0 {
return f
}
coeffs := e.computeCoeffs()
e.millerLoop((*fp12)(f), coeffs)
return f.FinalExponentiation(f)
}
func (e *Engine) millerLoop(f *fp12, coeffs []g2Prepared) {
newF := new(fp12).SetZero()
found := 0
cIdx := 0
for i := 63; i >= 0; i-- {
x := int(((paramX >> 1) >> i) & 1)
if found == 0 {
found |= x
continue
}
// doubling
for j, terms := range coeffs {
identity := e.pairs[j].g1.IsIdentity() | terms.identity
newF.Set(f)
ell(newF, terms.coefficients[cIdx], &e.pairs[j].g1)
f.CMove(newF, f, identity)
}
cIdx++
if x == 1 {
// adding
for j, terms := range coeffs {
identity := e.pairs[j].g1.IsIdentity() | terms.identity
newF.Set(f)
ell(newF, terms.coefficients[cIdx], &e.pairs[j].g1)
f.CMove(newF, f, identity)
}
cIdx++
}
f.Square(f)
}
for j, terms := range coeffs {
identity := e.pairs[j].g1.IsIdentity() | terms.identity
newF.Set(f)
ell(newF, terms.coefficients[cIdx], &e.pairs[j].g1)
f.CMove(newF, f, identity)
}
f.Conjugate(f)
}
func (e *Engine) computeCoeffs() []g2Prepared {
coeffs := make([]g2Prepared, len(e.pairs))
for i, p := range e.pairs {
identity := p.g2.IsIdentity()
q := new(G2).Generator()
q.CMove(&p.g2, q, identity)
c := new(G2).Set(q)
cfs := make([]coefficients, coefficientsG2)
found := 0
k := 0
for j := 63; j >= 0; j-- {
x := int(((paramX >> 1) >> j) & 1)
if found == 0 {
found |= x
continue
}
cfs[k] = doublingStep(c)
k++
if x == 1 {
cfs[k] = additionStep(c, q)
k++
}
}
cfs[k] = doublingStep(c)
coeffs[i] = g2Prepared{
coefficients: cfs, identity: identity,
}
}
return coeffs
}
func ell(f *fp12, coeffs coefficients, p *G1) {
var x, y fp2
x.A.Mul(&coeffs.a.A, &p.y)
x.B.Mul(&coeffs.a.B, &p.y)
y.A.Mul(&coeffs.b.A, &p.x)
y.B.Mul(&coeffs.b.B, &p.x)
f.MulByABD(f, &coeffs.c, &y, &x)
}
func doublingStep(p *G2) coefficients {
// Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
var t0, t1, t2, t3, t4, t5, t6, zsqr fp2
t0.Square(&p.x)
t1.Square(&p.y)
t2.Square(&t1)
t3.Add(&t1, &p.x)
t3.Square(&t3)
t3.Sub(&t3, &t0)
t3.Sub(&t3, &t2)
t3.Double(&t3)
t4.Double(&t0)
t4.Add(&t4, &t0)
t6.Add(&p.x, &t4)
t5.Square(&t4)
zsqr.Square(&p.z)
p.x.Sub(&t5, &t3)
p.x.Sub(&p.x, &t3)
p.z.Add(&p.z, &p.y)
p.z.Square(&p.z)
p.z.Sub(&p.z, &t1)
p.z.Sub(&p.z, &zsqr)
p.y.Sub(&t3, &p.x)
p.y.Mul(&p.y, &t4)
t2.Double(&t2)
t2.Double(&t2)
t2.Double(&t2)
p.y.Sub(&p.y, &t2)
t3.Mul(&t4, &zsqr)
t3.Double(&t3)
t3.Neg(&t3)
t6.Square(&t6)
t6.Sub(&t6, &t0)
t6.Sub(&t6, &t5)
t1.Double(&t1)
t1.Double(&t1)
t6.Sub(&t6, &t1)
t0.Mul(&p.z, &zsqr)
t0.Double(&t0)
return coefficients{
a: t0, b: t3, c: t6,
}
}
func additionStep(r, q *G2) coefficients {
// Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
var zsqr, ysqr fp2
var t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10 fp2
zsqr.Square(&r.z)
ysqr.Square(&q.y)
t0.Mul(&zsqr, &q.x)
t1.Add(&q.y, &r.z)
t1.Square(&t1)
t1.Sub(&t1, &ysqr)
t1.Sub(&t1, &zsqr)
t1.Mul(&t1, &zsqr)
t2.Sub(&t0, &r.x)
t3.Square(&t2)
t4.Double(&t3)
t4.Double(&t4)
t5.Mul(&t4, &t2)
t6.Sub(&t1, &r.y)
t6.Sub(&t6, &r.y)
t9.Mul(&t6, &q.x)
t7.Mul(&t4, &r.x)
r.x.Square(&t6)
r.x.Sub(&r.x, &t5)
r.x.Sub(&r.x, &t7)
r.x.Sub(&r.x, &t7)
r.z.Add(&r.z, &t2)
r.z.Square(&r.z)
r.z.Sub(&r.z, &zsqr)
r.z.Sub(&r.z, &t3)
t10.Add(&q.y, &r.z)
t8.Sub(&t7, &r.x)
t8.Mul(&t8, &t6)
t0.Mul(&r.y, &t5)
t0.Double(&t0)
r.y.Sub(&t8, &t0)
t10.Square(&t10)
t10.Sub(&t10, &ysqr)
zsqr.Square(&r.z)
t10.Sub(&t10, &zsqr)
t9.Double(&t9)
t9.Sub(&t9, &t10)
t10.Double(&r.z)
t6.Neg(&t6)
t1.Double(&t6)
return coefficients{
a: t10, b: t1, c: t9,
}
}