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

341 lines
6.2 KiB
Go
Executable File

package bls12381
import "io"
// fp6 represents an element
// a + b v + c v^2 of fp^6 = fp^2 / v^3 - u - 1.
type fp6 struct {
A, B, C fp2
}
// Set fp6 = a
func (f *fp6) Set(a *fp6) *fp6 {
f.A.Set(&a.A)
f.B.Set(&a.B)
f.C.Set(&a.C)
return f
}
// SetFp creates an element from a lower field
func (f *fp6) SetFp(a *fp) *fp6 {
f.A.SetFp(a)
f.B.SetZero()
f.C.SetZero()
return f
}
// SetFp2 creates an element from a lower field
func (f *fp6) SetFp2(a *fp2) *fp6 {
f.A.Set(a)
f.B.SetZero()
f.C.SetZero()
return f
}
// SetZero fp6 to zero
func (f *fp6) SetZero() *fp6 {
f.A.SetZero()
f.B.SetZero()
f.C.SetZero()
return f
}
// SetOne fp6 to multiplicative identity element
func (f *fp6) SetOne() *fp6 {
f.A.SetOne()
f.B.SetZero()
f.C.SetZero()
return f
}
// Random generates a random field element
func (f *fp6) Random(reader io.Reader) (*fp6, error) {
a, err := new(fp2).Random(reader)
if err != nil {
return nil, err
}
b, err := new(fp2).Random(reader)
if err != nil {
return nil, err
}
c, err := new(fp2).Random(reader)
if err != nil {
return nil, err
}
f.A.Set(a)
f.B.Set(b)
f.C.Set(c)
return f, nil
}
// Add computes arg1+arg2
func (f *fp6) Add(arg1, arg2 *fp6) *fp6 {
f.A.Add(&arg1.A, &arg2.A)
f.B.Add(&arg1.B, &arg2.B)
f.C.Add(&arg1.C, &arg2.C)
return f
}
// Double computes arg1+arg1
func (f *fp6) Double(arg *fp6) *fp6 {
return f.Add(arg, arg)
}
// Sub computes arg1-arg2
func (f *fp6) Sub(arg1, arg2 *fp6) *fp6 {
f.A.Sub(&arg1.A, &arg2.A)
f.B.Sub(&arg1.B, &arg2.B)
f.C.Sub(&arg1.C, &arg2.C)
return f
}
// Mul computes arg1*arg2
func (f *fp6) Mul(arg1, arg2 *fp6) *fp6 {
var aa, bb, cc, s, t1, t2, t3 fp2
aa.Mul(&arg1.A, &arg2.A)
bb.Mul(&arg1.B, &arg2.B)
cc.Mul(&arg1.C, &arg2.C)
t1.Add(&arg2.B, &arg2.C)
s.Add(&arg1.B, &arg1.C)
t1.Mul(&t1, &s)
t1.Sub(&t1, &bb)
t1.Sub(&t1, &cc)
t1.MulByNonResidue(&t1)
t1.Add(&t1, &aa)
t3.Add(&arg2.A, &arg2.C)
s.Add(&arg1.A, &arg1.C)
t3.Mul(&t3, &s)
t3.Sub(&t3, &aa)
t3.Add(&t3, &bb)
t3.Sub(&t3, &cc)
t2.Add(&arg2.A, &arg2.B)
s.Add(&arg1.A, &arg1.B)
t2.Mul(&t2, &s)
t2.Sub(&t2, &aa)
t2.Sub(&t2, &bb)
cc.MulByNonResidue(&cc)
t2.Add(&t2, &cc)
f.A.Set(&t1)
f.B.Set(&t2)
f.C.Set(&t3)
return f
}
// MulByB scales this field by a scalar in the B coefficient
func (f *fp6) MulByB(arg *fp6, b *fp2) *fp6 {
var bB, t1, t2 fp2
bB.Mul(&arg.B, b)
// (b + c) * arg2 - bB
t1.Add(&arg.B, &arg.C)
t1.Mul(&t1, b)
t1.Sub(&t1, &bB)
t1.MulByNonResidue(&t1)
t2.Add(&arg.A, &arg.B)
t2.Mul(&t2, b)
t2.Sub(&t2, &bB)
f.A.Set(&t1)
f.B.Set(&t2)
f.C.Set(&bB)
return f
}
// MulByAB scales this field by scalars in the A and B coefficients
func (f *fp6) MulByAB(arg *fp6, a, b *fp2) *fp6 {
var aA, bB, t1, t2, t3 fp2
aA.Mul(&arg.A, a)
bB.Mul(&arg.B, b)
t1.Add(&arg.B, &arg.C)
t1.Mul(&t1, b)
t1.Sub(&t1, &bB)
t1.MulByNonResidue(&t1)
t1.Add(&t1, &aA)
t2.Add(a, b)
t3.Add(&arg.A, &arg.B)
t2.Mul(&t2, &t3)
t2.Sub(&t2, &aA)
t2.Sub(&t2, &bB)
t3.Add(&arg.A, &arg.C)
t3.Mul(&t3, a)
t3.Sub(&t3, &aA)
t3.Add(&t3, &bB)
f.A.Set(&t1)
f.B.Set(&t2)
f.C.Set(&t3)
return f
}
// MulByNonResidue multiplies by quadratic nonresidue v.
func (f *fp6) MulByNonResidue(arg *fp6) *fp6 {
// Given a + bv + cv^2, this produces
// av + bv^2 + cv^3
// but because v^3 = u + 1, we have
// c(u + 1) + av + bv^2
var a, b, c fp2
a.MulByNonResidue(&arg.C)
b.Set(&arg.A)
c.Set(&arg.B)
f.A.Set(&a)
f.B.Set(&b)
f.C.Set(&c)
return f
}
// FrobeniusMap raises this element to p.
func (f *fp6) FrobeniusMap(arg *fp6) *fp6 {
var a, b, c fp2
pm1Div3 := fp2{
A: fp{},
B: fp{
0xcd03c9e48671f071,
0x5dab22461fcda5d2,
0x587042afd3851b95,
0x8eb60ebe01bacb9e,
0x03f97d6e83d050d2,
0x18f0206554638741,
},
}
p2m2Div3 := fp2{
A: fp{
0x890dc9e4867545c3,
0x2af322533285a5d5,
0x50880866309b7e2c,
0xa20d1b8c7e881024,
0x14e4f04fe2db9068,
0x14e56d3f1564853a,
},
B: fp{},
}
a.FrobeniusMap(&arg.A)
b.FrobeniusMap(&arg.B)
c.FrobeniusMap(&arg.C)
// b = b * (u + 1)^((p - 1) / 3)
b.Mul(&b, &pm1Div3)
// c = c * (u + 1)^((2p - 2) / 3)
c.Mul(&c, &p2m2Div3)
f.A.Set(&a)
f.B.Set(&b)
f.C.Set(&c)
return f
}
// Square computes fp6^2
func (f *fp6) Square(arg *fp6) *fp6 {
var s0, s1, s2, s3, s4, ab, bc fp2
s0.Square(&arg.A)
ab.Mul(&arg.A, &arg.B)
s1.Double(&ab)
s2.Sub(&arg.A, &arg.B)
s2.Add(&s2, &arg.C)
s2.Square(&s2)
bc.Mul(&arg.B, &arg.C)
s3.Double(&bc)
s4.Square(&arg.C)
f.A.MulByNonResidue(&s3)
f.A.Add(&f.A, &s0)
f.B.MulByNonResidue(&s4)
f.B.Add(&f.B, &s1)
// s1 + s2 + s3 - s0 - s4
f.C.Add(&s1, &s2)
f.C.Add(&f.C, &s3)
f.C.Sub(&f.C, &s0)
f.C.Sub(&f.C, &s4)
return f
}
// Invert computes this element's field inversion
func (f *fp6) Invert(arg *fp6) (*fp6, int) {
var a, b, c, s, t fp2
// a' = a^2 - (b * c).mul_by_nonresidue()
a.Mul(&arg.B, &arg.C)
a.MulByNonResidue(&a)
t.Square(&arg.A)
a.Sub(&t, &a)
// b' = (c^2).mul_by_nonresidue() - (a * b)
b.Square(&arg.C)
b.MulByNonResidue(&b)
t.Mul(&arg.A, &arg.B)
b.Sub(&b, &t)
// c' = b^2 - (a * c)
c.Square(&arg.B)
t.Mul(&arg.A, &arg.C)
c.Sub(&c, &t)
// t = ((b * c') + (c * b')).mul_by_nonresidue() + (a * a')
s.Mul(&arg.B, &c)
t.Mul(&arg.C, &b)
s.Add(&s, &t)
s.MulByNonResidue(&s)
t.Mul(&arg.A, &a)
s.Add(&s, &t)
_, wasInverted := t.Invert(&s)
// newA = a' * t^-1
s.Mul(&a, &t)
f.A.CMove(&f.A, &s, wasInverted)
// newB = b' * t^-1
s.Mul(&b, &t)
f.B.CMove(&f.B, &s, wasInverted)
// newC = c' * t^-1
s.Mul(&c, &t)
f.C.CMove(&f.C, &s, wasInverted)
return f, wasInverted
}
// Neg computes the field negation
func (f *fp6) Neg(arg *fp6) *fp6 {
f.A.Neg(&arg.A)
f.B.Neg(&arg.B)
f.C.Neg(&arg.C)
return f
}
// IsZero returns 1 if fp6 == 0, 0 otherwise
func (f *fp6) IsZero() int {
return f.A.IsZero() & f.B.IsZero() & f.C.IsZero()
}
// IsOne returns 1 if fp6 == 1, 0 otherwise
func (f *fp6) IsOne() int {
return f.A.IsOne() & f.B.IsZero() & f.B.IsZero()
}
// Equal returns 1 if fp6 == rhs, 0 otherwise
func (f *fp6) Equal(rhs *fp6) int {
return f.A.Equal(&rhs.A) & f.B.Equal(&rhs.B) & f.C.Equal(&rhs.C)
}
// CMove performs conditional select.
// selects arg1 if choice == 0 and arg2 if choice == 1
func (f *fp6) CMove(arg1, arg2 *fp6, choice int) *fp6 {
f.A.CMove(&arg1.A, &arg2.A, choice)
f.B.CMove(&arg1.B, &arg2.B, choice)
f.C.CMove(&arg1.C, &arg2.C, choice)
return f
}