Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
cc3de083
Commit
cc3de083
authored
Sep 13, 2021
by
George Hotz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bls12381 system
parent
f193a1b2
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
3910 additions
and
2 deletions
+3910
-2
contracts.go
minigeth/core/vm/contracts.go
+2
-2
arithmetic_fallback.go
minigeth/crypto/bls12381/arithmetic_fallback.go
+566
-0
bls12_381.go
minigeth/crypto/bls12381/bls12_381.go
+230
-0
field_element.go
minigeth/crypto/bls12381/field_element.go
+340
-0
fp.go
minigeth/crypto/bls12381/fp.go
+167
-0
fp12.go
minigeth/crypto/bls12381/fp12.go
+279
-0
fp2.go
minigeth/crypto/bls12381/fp2.go
+252
-0
fp6.go
minigeth/crypto/bls12381/fp6.go
+351
-0
g1.go
minigeth/crypto/bls12381/g1.go
+434
-0
g2.go
minigeth/crypto/bls12381/g2.go
+456
-0
gt.go
minigeth/crypto/bls12381/gt.go
+121
-0
isogeny.go
minigeth/crypto/bls12381/isogeny.go
+227
-0
pairing.go
minigeth/crypto/bls12381/pairing.go
+282
-0
swu.go
minigeth/crypto/bls12381/swu.go
+158
-0
utils.go
minigeth/crypto/bls12381/utils.go
+45
-0
.bn256_slow.go.swp
minigeth/crypto/bn256/.bn256_slow.go.swp
+0
-0
No files found.
minigeth/core/vm/contracts.go
View file @
cc3de083
...
...
@@ -26,8 +26,8 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
/*"github.com/ethereum/go-ethereum/crypto/blake2b"
"github.com/ethereum/go-ethereum/crypto/bls12381"
*/
/*"github.com/ethereum/go-ethereum/crypto/blake2b"
*/
"github.com/ethereum/go-ethereum/crypto/bls12381"
"github.com/ethereum/go-ethereum/crypto/bn256"
"github.com/ethereum/go-ethereum/params"
...
...
minigeth/crypto/bls12381/arithmetic_fallback.go
0 → 100644
View file @
cc3de083
// Native go field arithmetic code is generated with 'goff'
// https://github.com/ConsenSys/goff
// Many function signature of field operations are renamed.
// Copyright 2020 ConsenSys AG
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// field modulus q =
//
// 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
// Code generated by goff DO NOT EDIT
// goff version: v0.1.0 - build: 790f1f56eac432441e043abff8819eacddd1d668
// fe are assumed to be in Montgomery form in all methods
// /!\ WARNING /!\
// this code has not been audited and is provided as-is. In particular,
// there is no security guarantees such as constant time implementation
// or side-channel attack resistance
// /!\ WARNING /!\
// Package bls (generated by goff) contains field arithmetics operations
// +build !amd64 !blsasm,!blsadx
package
bls12381
import
(
"math/bits"
)
func
add
(
z
,
x
,
y
*
fe
)
{
var
carry
uint64
z
[
0
],
carry
=
bits
.
Add64
(
x
[
0
],
y
[
0
],
0
)
z
[
1
],
carry
=
bits
.
Add64
(
x
[
1
],
y
[
1
],
carry
)
z
[
2
],
carry
=
bits
.
Add64
(
x
[
2
],
y
[
2
],
carry
)
z
[
3
],
carry
=
bits
.
Add64
(
x
[
3
],
y
[
3
],
carry
)
z
[
4
],
carry
=
bits
.
Add64
(
x
[
4
],
y
[
4
],
carry
)
z
[
5
],
_
=
bits
.
Add64
(
x
[
5
],
y
[
5
],
carry
)
// if z > q --> z -= q
// note: this is NOT constant time
if
!
(
z
[
5
]
<
1873798617647539866
||
(
z
[
5
]
==
1873798617647539866
&&
(
z
[
4
]
<
5412103778470702295
||
(
z
[
4
]
==
5412103778470702295
&&
(
z
[
3
]
<
7239337960414712511
||
(
z
[
3
]
==
7239337960414712511
&&
(
z
[
2
]
<
7435674573564081700
||
(
z
[
2
]
==
7435674573564081700
&&
(
z
[
1
]
<
2210141511517208575
||
(
z
[
1
]
==
2210141511517208575
&&
(
z
[
0
]
<
13402431016077863595
)))))))))))
{
var
b
uint64
z
[
0
],
b
=
bits
.
Sub64
(
z
[
0
],
13402431016077863595
,
0
)
z
[
1
],
b
=
bits
.
Sub64
(
z
[
1
],
2210141511517208575
,
b
)
z
[
2
],
b
=
bits
.
Sub64
(
z
[
2
],
7435674573564081700
,
b
)
z
[
3
],
b
=
bits
.
Sub64
(
z
[
3
],
7239337960414712511
,
b
)
z
[
4
],
b
=
bits
.
Sub64
(
z
[
4
],
5412103778470702295
,
b
)
z
[
5
],
_
=
bits
.
Sub64
(
z
[
5
],
1873798617647539866
,
b
)
}
}
func
addAssign
(
x
,
y
*
fe
)
{
var
carry
uint64
x
[
0
],
carry
=
bits
.
Add64
(
x
[
0
],
y
[
0
],
0
)
x
[
1
],
carry
=
bits
.
Add64
(
x
[
1
],
y
[
1
],
carry
)
x
[
2
],
carry
=
bits
.
Add64
(
x
[
2
],
y
[
2
],
carry
)
x
[
3
],
carry
=
bits
.
Add64
(
x
[
3
],
y
[
3
],
carry
)
x
[
4
],
carry
=
bits
.
Add64
(
x
[
4
],
y
[
4
],
carry
)
x
[
5
],
_
=
bits
.
Add64
(
x
[
5
],
y
[
5
],
carry
)
// if z > q --> z -= q
// note: this is NOT constant time
if
!
(
x
[
5
]
<
1873798617647539866
||
(
x
[
5
]
==
1873798617647539866
&&
(
x
[
4
]
<
5412103778470702295
||
(
x
[
4
]
==
5412103778470702295
&&
(
x
[
3
]
<
7239337960414712511
||
(
x
[
3
]
==
7239337960414712511
&&
(
x
[
2
]
<
7435674573564081700
||
(
x
[
2
]
==
7435674573564081700
&&
(
x
[
1
]
<
2210141511517208575
||
(
x
[
1
]
==
2210141511517208575
&&
(
x
[
0
]
<
13402431016077863595
)))))))))))
{
var
b
uint64
x
[
0
],
b
=
bits
.
Sub64
(
x
[
0
],
13402431016077863595
,
0
)
x
[
1
],
b
=
bits
.
Sub64
(
x
[
1
],
2210141511517208575
,
b
)
x
[
2
],
b
=
bits
.
Sub64
(
x
[
2
],
7435674573564081700
,
b
)
x
[
3
],
b
=
bits
.
Sub64
(
x
[
3
],
7239337960414712511
,
b
)
x
[
4
],
b
=
bits
.
Sub64
(
x
[
4
],
5412103778470702295
,
b
)
x
[
5
],
_
=
bits
.
Sub64
(
x
[
5
],
1873798617647539866
,
b
)
}
}
func
ladd
(
z
,
x
,
y
*
fe
)
{
var
carry
uint64
z
[
0
],
carry
=
bits
.
Add64
(
x
[
0
],
y
[
0
],
0
)
z
[
1
],
carry
=
bits
.
Add64
(
x
[
1
],
y
[
1
],
carry
)
z
[
2
],
carry
=
bits
.
Add64
(
x
[
2
],
y
[
2
],
carry
)
z
[
3
],
carry
=
bits
.
Add64
(
x
[
3
],
y
[
3
],
carry
)
z
[
4
],
carry
=
bits
.
Add64
(
x
[
4
],
y
[
4
],
carry
)
z
[
5
],
_
=
bits
.
Add64
(
x
[
5
],
y
[
5
],
carry
)
}
func
laddAssign
(
x
,
y
*
fe
)
{
var
carry
uint64
x
[
0
],
carry
=
bits
.
Add64
(
x
[
0
],
y
[
0
],
0
)
x
[
1
],
carry
=
bits
.
Add64
(
x
[
1
],
y
[
1
],
carry
)
x
[
2
],
carry
=
bits
.
Add64
(
x
[
2
],
y
[
2
],
carry
)
x
[
3
],
carry
=
bits
.
Add64
(
x
[
3
],
y
[
3
],
carry
)
x
[
4
],
carry
=
bits
.
Add64
(
x
[
4
],
y
[
4
],
carry
)
x
[
5
],
_
=
bits
.
Add64
(
x
[
5
],
y
[
5
],
carry
)
}
func
double
(
z
,
x
*
fe
)
{
var
carry
uint64
z
[
0
],
carry
=
bits
.
Add64
(
x
[
0
],
x
[
0
],
0
)
z
[
1
],
carry
=
bits
.
Add64
(
x
[
1
],
x
[
1
],
carry
)
z
[
2
],
carry
=
bits
.
Add64
(
x
[
2
],
x
[
2
],
carry
)
z
[
3
],
carry
=
bits
.
Add64
(
x
[
3
],
x
[
3
],
carry
)
z
[
4
],
carry
=
bits
.
Add64
(
x
[
4
],
x
[
4
],
carry
)
z
[
5
],
_
=
bits
.
Add64
(
x
[
5
],
x
[
5
],
carry
)
// if z > q --> z -= q
// note: this is NOT constant time
if
!
(
z
[
5
]
<
1873798617647539866
||
(
z
[
5
]
==
1873798617647539866
&&
(
z
[
4
]
<
5412103778470702295
||
(
z
[
4
]
==
5412103778470702295
&&
(
z
[
3
]
<
7239337960414712511
||
(
z
[
3
]
==
7239337960414712511
&&
(
z
[
2
]
<
7435674573564081700
||
(
z
[
2
]
==
7435674573564081700
&&
(
z
[
1
]
<
2210141511517208575
||
(
z
[
1
]
==
2210141511517208575
&&
(
z
[
0
]
<
13402431016077863595
)))))))))))
{
var
b
uint64
z
[
0
],
b
=
bits
.
Sub64
(
z
[
0
],
13402431016077863595
,
0
)
z
[
1
],
b
=
bits
.
Sub64
(
z
[
1
],
2210141511517208575
,
b
)
z
[
2
],
b
=
bits
.
Sub64
(
z
[
2
],
7435674573564081700
,
b
)
z
[
3
],
b
=
bits
.
Sub64
(
z
[
3
],
7239337960414712511
,
b
)
z
[
4
],
b
=
bits
.
Sub64
(
z
[
4
],
5412103778470702295
,
b
)
z
[
5
],
_
=
bits
.
Sub64
(
z
[
5
],
1873798617647539866
,
b
)
}
}
func
doubleAssign
(
z
*
fe
)
{
var
carry
uint64
z
[
0
],
carry
=
bits
.
Add64
(
z
[
0
],
z
[
0
],
0
)
z
[
1
],
carry
=
bits
.
Add64
(
z
[
1
],
z
[
1
],
carry
)
z
[
2
],
carry
=
bits
.
Add64
(
z
[
2
],
z
[
2
],
carry
)
z
[
3
],
carry
=
bits
.
Add64
(
z
[
3
],
z
[
3
],
carry
)
z
[
4
],
carry
=
bits
.
Add64
(
z
[
4
],
z
[
4
],
carry
)
z
[
5
],
_
=
bits
.
Add64
(
z
[
5
],
z
[
5
],
carry
)
// if z > q --> z -= q
// note: this is NOT constant time
if
!
(
z
[
5
]
<
1873798617647539866
||
(
z
[
5
]
==
1873798617647539866
&&
(
z
[
4
]
<
5412103778470702295
||
(
z
[
4
]
==
5412103778470702295
&&
(
z
[
3
]
<
7239337960414712511
||
(
z
[
3
]
==
7239337960414712511
&&
(
z
[
2
]
<
7435674573564081700
||
(
z
[
2
]
==
7435674573564081700
&&
(
z
[
1
]
<
2210141511517208575
||
(
z
[
1
]
==
2210141511517208575
&&
(
z
[
0
]
<
13402431016077863595
)))))))))))
{
var
b
uint64
z
[
0
],
b
=
bits
.
Sub64
(
z
[
0
],
13402431016077863595
,
0
)
z
[
1
],
b
=
bits
.
Sub64
(
z
[
1
],
2210141511517208575
,
b
)
z
[
2
],
b
=
bits
.
Sub64
(
z
[
2
],
7435674573564081700
,
b
)
z
[
3
],
b
=
bits
.
Sub64
(
z
[
3
],
7239337960414712511
,
b
)
z
[
4
],
b
=
bits
.
Sub64
(
z
[
4
],
5412103778470702295
,
b
)
z
[
5
],
_
=
bits
.
Sub64
(
z
[
5
],
1873798617647539866
,
b
)
}
}
func
ldouble
(
z
,
x
*
fe
)
{
var
carry
uint64
z
[
0
],
carry
=
bits
.
Add64
(
x
[
0
],
x
[
0
],
0
)
z
[
1
],
carry
=
bits
.
Add64
(
x
[
1
],
x
[
1
],
carry
)
z
[
2
],
carry
=
bits
.
Add64
(
x
[
2
],
x
[
2
],
carry
)
z
[
3
],
carry
=
bits
.
Add64
(
x
[
3
],
x
[
3
],
carry
)
z
[
4
],
carry
=
bits
.
Add64
(
x
[
4
],
x
[
4
],
carry
)
z
[
5
],
_
=
bits
.
Add64
(
x
[
5
],
x
[
5
],
carry
)
}
func
sub
(
z
,
x
,
y
*
fe
)
{
var
b
uint64
z
[
0
],
b
=
bits
.
Sub64
(
x
[
0
],
y
[
0
],
0
)
z
[
1
],
b
=
bits
.
Sub64
(
x
[
1
],
y
[
1
],
b
)
z
[
2
],
b
=
bits
.
Sub64
(
x
[
2
],
y
[
2
],
b
)
z
[
3
],
b
=
bits
.
Sub64
(
x
[
3
],
y
[
3
],
b
)
z
[
4
],
b
=
bits
.
Sub64
(
x
[
4
],
y
[
4
],
b
)
z
[
5
],
b
=
bits
.
Sub64
(
x
[
5
],
y
[
5
],
b
)
if
b
!=
0
{
var
c
uint64
z
[
0
],
c
=
bits
.
Add64
(
z
[
0
],
13402431016077863595
,
0
)
z
[
1
],
c
=
bits
.
Add64
(
z
[
1
],
2210141511517208575
,
c
)
z
[
2
],
c
=
bits
.
Add64
(
z
[
2
],
7435674573564081700
,
c
)
z
[
3
],
c
=
bits
.
Add64
(
z
[
3
],
7239337960414712511
,
c
)
z
[
4
],
c
=
bits
.
Add64
(
z
[
4
],
5412103778470702295
,
c
)
z
[
5
],
_
=
bits
.
Add64
(
z
[
5
],
1873798617647539866
,
c
)
}
}
func
subAssign
(
z
,
x
*
fe
)
{
var
b
uint64
z
[
0
],
b
=
bits
.
Sub64
(
z
[
0
],
x
[
0
],
0
)
z
[
1
],
b
=
bits
.
Sub64
(
z
[
1
],
x
[
1
],
b
)
z
[
2
],
b
=
bits
.
Sub64
(
z
[
2
],
x
[
2
],
b
)
z
[
3
],
b
=
bits
.
Sub64
(
z
[
3
],
x
[
3
],
b
)
z
[
4
],
b
=
bits
.
Sub64
(
z
[
4
],
x
[
4
],
b
)
z
[
5
],
b
=
bits
.
Sub64
(
z
[
5
],
x
[
5
],
b
)
if
b
!=
0
{
var
c
uint64
z
[
0
],
c
=
bits
.
Add64
(
z
[
0
],
13402431016077863595
,
0
)
z
[
1
],
c
=
bits
.
Add64
(
z
[
1
],
2210141511517208575
,
c
)
z
[
2
],
c
=
bits
.
Add64
(
z
[
2
],
7435674573564081700
,
c
)
z
[
3
],
c
=
bits
.
Add64
(
z
[
3
],
7239337960414712511
,
c
)
z
[
4
],
c
=
bits
.
Add64
(
z
[
4
],
5412103778470702295
,
c
)
z
[
5
],
_
=
bits
.
Add64
(
z
[
5
],
1873798617647539866
,
c
)
}
}
func
lsubAssign
(
z
,
x
*
fe
)
{
var
b
uint64
z
[
0
],
b
=
bits
.
Sub64
(
z
[
0
],
x
[
0
],
0
)
z
[
1
],
b
=
bits
.
Sub64
(
z
[
1
],
x
[
1
],
b
)
z
[
2
],
b
=
bits
.
Sub64
(
z
[
2
],
x
[
2
],
b
)
z
[
3
],
b
=
bits
.
Sub64
(
z
[
3
],
x
[
3
],
b
)
z
[
4
],
b
=
bits
.
Sub64
(
z
[
4
],
x
[
4
],
b
)
z
[
5
],
_
=
bits
.
Sub64
(
z
[
5
],
x
[
5
],
b
)
}
func
neg
(
z
*
fe
,
x
*
fe
)
{
if
x
.
isZero
()
{
z
.
zero
()
return
}
var
borrow
uint64
z
[
0
],
borrow
=
bits
.
Sub64
(
13402431016077863595
,
x
[
0
],
0
)
z
[
1
],
borrow
=
bits
.
Sub64
(
2210141511517208575
,
x
[
1
],
borrow
)
z
[
2
],
borrow
=
bits
.
Sub64
(
7435674573564081700
,
x
[
2
],
borrow
)
z
[
3
],
borrow
=
bits
.
Sub64
(
7239337960414712511
,
x
[
3
],
borrow
)
z
[
4
],
borrow
=
bits
.
Sub64
(
5412103778470702295
,
x
[
4
],
borrow
)
z
[
5
],
_
=
bits
.
Sub64
(
1873798617647539866
,
x
[
5
],
borrow
)
}
func
mul
(
z
,
x
,
y
*
fe
)
{
var
t
[
6
]
uint64
var
c
[
3
]
uint64
{
// round 0
v
:=
x
[
0
]
c
[
1
],
c
[
0
]
=
bits
.
Mul64
(
v
,
y
[
0
])
m
:=
c
[
0
]
*
9940570264628428797
c
[
2
]
=
madd0
(
m
,
13402431016077863595
,
c
[
0
])
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
1
],
c
[
1
])
c
[
2
],
t
[
0
]
=
madd2
(
m
,
2210141511517208575
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
2
],
c
[
1
])
c
[
2
],
t
[
1
]
=
madd2
(
m
,
7435674573564081700
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
3
],
c
[
1
])
c
[
2
],
t
[
2
]
=
madd2
(
m
,
7239337960414712511
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
4
],
c
[
1
])
c
[
2
],
t
[
3
]
=
madd2
(
m
,
5412103778470702295
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
5
],
c
[
1
])
t
[
5
],
t
[
4
]
=
madd3
(
m
,
1873798617647539866
,
c
[
0
],
c
[
2
],
c
[
1
])
}
{
// round 1
v
:=
x
[
1
]
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
0
],
t
[
0
])
m
:=
c
[
0
]
*
9940570264628428797
c
[
2
]
=
madd0
(
m
,
13402431016077863595
,
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
1
],
c
[
1
],
t
[
1
])
c
[
2
],
t
[
0
]
=
madd2
(
m
,
2210141511517208575
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
2
],
c
[
1
],
t
[
2
])
c
[
2
],
t
[
1
]
=
madd2
(
m
,
7435674573564081700
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
3
],
c
[
1
],
t
[
3
])
c
[
2
],
t
[
2
]
=
madd2
(
m
,
7239337960414712511
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
4
],
c
[
1
],
t
[
4
])
c
[
2
],
t
[
3
]
=
madd2
(
m
,
5412103778470702295
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
5
],
c
[
1
],
t
[
5
])
t
[
5
],
t
[
4
]
=
madd3
(
m
,
1873798617647539866
,
c
[
0
],
c
[
2
],
c
[
1
])
}
{
// round 2
v
:=
x
[
2
]
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
0
],
t
[
0
])
m
:=
c
[
0
]
*
9940570264628428797
c
[
2
]
=
madd0
(
m
,
13402431016077863595
,
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
1
],
c
[
1
],
t
[
1
])
c
[
2
],
t
[
0
]
=
madd2
(
m
,
2210141511517208575
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
2
],
c
[
1
],
t
[
2
])
c
[
2
],
t
[
1
]
=
madd2
(
m
,
7435674573564081700
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
3
],
c
[
1
],
t
[
3
])
c
[
2
],
t
[
2
]
=
madd2
(
m
,
7239337960414712511
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
4
],
c
[
1
],
t
[
4
])
c
[
2
],
t
[
3
]
=
madd2
(
m
,
5412103778470702295
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
5
],
c
[
1
],
t
[
5
])
t
[
5
],
t
[
4
]
=
madd3
(
m
,
1873798617647539866
,
c
[
0
],
c
[
2
],
c
[
1
])
}
{
// round 3
v
:=
x
[
3
]
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
0
],
t
[
0
])
m
:=
c
[
0
]
*
9940570264628428797
c
[
2
]
=
madd0
(
m
,
13402431016077863595
,
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
1
],
c
[
1
],
t
[
1
])
c
[
2
],
t
[
0
]
=
madd2
(
m
,
2210141511517208575
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
2
],
c
[
1
],
t
[
2
])
c
[
2
],
t
[
1
]
=
madd2
(
m
,
7435674573564081700
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
3
],
c
[
1
],
t
[
3
])
c
[
2
],
t
[
2
]
=
madd2
(
m
,
7239337960414712511
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
4
],
c
[
1
],
t
[
4
])
c
[
2
],
t
[
3
]
=
madd2
(
m
,
5412103778470702295
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
5
],
c
[
1
],
t
[
5
])
t
[
5
],
t
[
4
]
=
madd3
(
m
,
1873798617647539866
,
c
[
0
],
c
[
2
],
c
[
1
])
}
{
// round 4
v
:=
x
[
4
]
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
0
],
t
[
0
])
m
:=
c
[
0
]
*
9940570264628428797
c
[
2
]
=
madd0
(
m
,
13402431016077863595
,
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
1
],
c
[
1
],
t
[
1
])
c
[
2
],
t
[
0
]
=
madd2
(
m
,
2210141511517208575
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
2
],
c
[
1
],
t
[
2
])
c
[
2
],
t
[
1
]
=
madd2
(
m
,
7435674573564081700
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
3
],
c
[
1
],
t
[
3
])
c
[
2
],
t
[
2
]
=
madd2
(
m
,
7239337960414712511
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
4
],
c
[
1
],
t
[
4
])
c
[
2
],
t
[
3
]
=
madd2
(
m
,
5412103778470702295
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
5
],
c
[
1
],
t
[
5
])
t
[
5
],
t
[
4
]
=
madd3
(
m
,
1873798617647539866
,
c
[
0
],
c
[
2
],
c
[
1
])
}
{
// round 5
v
:=
x
[
5
]
c
[
1
],
c
[
0
]
=
madd1
(
v
,
y
[
0
],
t
[
0
])
m
:=
c
[
0
]
*
9940570264628428797
c
[
2
]
=
madd0
(
m
,
13402431016077863595
,
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
1
],
c
[
1
],
t
[
1
])
c
[
2
],
z
[
0
]
=
madd2
(
m
,
2210141511517208575
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
2
],
c
[
1
],
t
[
2
])
c
[
2
],
z
[
1
]
=
madd2
(
m
,
7435674573564081700
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
3
],
c
[
1
],
t
[
3
])
c
[
2
],
z
[
2
]
=
madd2
(
m
,
7239337960414712511
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
4
],
c
[
1
],
t
[
4
])
c
[
2
],
z
[
3
]
=
madd2
(
m
,
5412103778470702295
,
c
[
2
],
c
[
0
])
c
[
1
],
c
[
0
]
=
madd2
(
v
,
y
[
5
],
c
[
1
],
t
[
5
])
z
[
5
],
z
[
4
]
=
madd3
(
m
,
1873798617647539866
,
c
[
0
],
c
[
2
],
c
[
1
])
}
// if z > q --> z -= q
// note: this is NOT constant time
if
!
(
z
[
5
]
<
1873798617647539866
||
(
z
[
5
]
==
1873798617647539866
&&
(
z
[
4
]
<
5412103778470702295
||
(
z
[
4
]
==
5412103778470702295
&&
(
z
[
3
]
<
7239337960414712511
||
(
z
[
3
]
==
7239337960414712511
&&
(
z
[
2
]
<
7435674573564081700
||
(
z
[
2
]
==
7435674573564081700
&&
(
z
[
1
]
<
2210141511517208575
||
(
z
[
1
]
==
2210141511517208575
&&
(
z
[
0
]
<
13402431016077863595
)))))))))))
{
var
b
uint64
z
[
0
],
b
=
bits
.
Sub64
(
z
[
0
],
13402431016077863595
,
0
)
z
[
1
],
b
=
bits
.
Sub64
(
z
[
1
],
2210141511517208575
,
b
)
z
[
2
],
b
=
bits
.
Sub64
(
z
[
2
],
7435674573564081700
,
b
)
z
[
3
],
b
=
bits
.
Sub64
(
z
[
3
],
7239337960414712511
,
b
)
z
[
4
],
b
=
bits
.
Sub64
(
z
[
4
],
5412103778470702295
,
b
)
z
[
5
],
_
=
bits
.
Sub64
(
z
[
5
],
1873798617647539866
,
b
)
}
}
func
square
(
z
,
x
*
fe
)
{
var
p
[
6
]
uint64
var
u
,
v
uint64
{
// round 0
u
,
p
[
0
]
=
bits
.
Mul64
(
x
[
0
],
x
[
0
])
m
:=
p
[
0
]
*
9940570264628428797
C
:=
madd0
(
m
,
13402431016077863595
,
p
[
0
])
var
t
uint64
t
,
u
,
v
=
madd1sb
(
x
[
0
],
x
[
1
],
u
)
C
,
p
[
0
]
=
madd2
(
m
,
2210141511517208575
,
v
,
C
)
t
,
u
,
v
=
madd1s
(
x
[
0
],
x
[
2
],
t
,
u
)
C
,
p
[
1
]
=
madd2
(
m
,
7435674573564081700
,
v
,
C
)
t
,
u
,
v
=
madd1s
(
x
[
0
],
x
[
3
],
t
,
u
)
C
,
p
[
2
]
=
madd2
(
m
,
7239337960414712511
,
v
,
C
)
t
,
u
,
v
=
madd1s
(
x
[
0
],
x
[
4
],
t
,
u
)
C
,
p
[
3
]
=
madd2
(
m
,
5412103778470702295
,
v
,
C
)
_
,
u
,
v
=
madd1s
(
x
[
0
],
x
[
5
],
t
,
u
)
p
[
5
],
p
[
4
]
=
madd3
(
m
,
1873798617647539866
,
v
,
C
,
u
)
}
{
// round 1
m
:=
p
[
0
]
*
9940570264628428797
C
:=
madd0
(
m
,
13402431016077863595
,
p
[
0
])
u
,
v
=
madd1
(
x
[
1
],
x
[
1
],
p
[
1
])
C
,
p
[
0
]
=
madd2
(
m
,
2210141511517208575
,
v
,
C
)
var
t
uint64
t
,
u
,
v
=
madd2sb
(
x
[
1
],
x
[
2
],
p
[
2
],
u
)
C
,
p
[
1
]
=
madd2
(
m
,
7435674573564081700
,
v
,
C
)
t
,
u
,
v
=
madd2s
(
x
[
1
],
x
[
3
],
p
[
3
],
t
,
u
)
C
,
p
[
2
]
=
madd2
(
m
,
7239337960414712511
,
v
,
C
)
t
,
u
,
v
=
madd2s
(
x
[
1
],
x
[
4
],
p
[
4
],
t
,
u
)
C
,
p
[
3
]
=
madd2
(
m
,
5412103778470702295
,
v
,
C
)
_
,
u
,
v
=
madd2s
(
x
[
1
],
x
[
5
],
p
[
5
],
t
,
u
)
p
[
5
],
p
[
4
]
=
madd3
(
m
,
1873798617647539866
,
v
,
C
,
u
)
}
{
// round 2
m
:=
p
[
0
]
*
9940570264628428797
C
:=
madd0
(
m
,
13402431016077863595
,
p
[
0
])
C
,
p
[
0
]
=
madd2
(
m
,
2210141511517208575
,
p
[
1
],
C
)
u
,
v
=
madd1
(
x
[
2
],
x
[
2
],
p
[
2
])
C
,
p
[
1
]
=
madd2
(
m
,
7435674573564081700
,
v
,
C
)
var
t
uint64
t
,
u
,
v
=
madd2sb
(
x
[
2
],
x
[
3
],
p
[
3
],
u
)
C
,
p
[
2
]
=
madd2
(
m
,
7239337960414712511
,
v
,
C
)
t
,
u
,
v
=
madd2s
(
x
[
2
],
x
[
4
],
p
[
4
],
t
,
u
)
C
,
p
[
3
]
=
madd2
(
m
,
5412103778470702295
,
v
,
C
)
_
,
u
,
v
=
madd2s
(
x
[
2
],
x
[
5
],
p
[
5
],
t
,
u
)
p
[
5
],
p
[
4
]
=
madd3
(
m
,
1873798617647539866
,
v
,
C
,
u
)
}
{
// round 3
m
:=
p
[
0
]
*
9940570264628428797
C
:=
madd0
(
m
,
13402431016077863595
,
p
[
0
])
C
,
p
[
0
]
=
madd2
(
m
,
2210141511517208575
,
p
[
1
],
C
)
C
,
p
[
1
]
=
madd2
(
m
,
7435674573564081700
,
p
[
2
],
C
)
u
,
v
=
madd1
(
x
[
3
],
x
[
3
],
p
[
3
])
C
,
p
[
2
]
=
madd2
(
m
,
7239337960414712511
,
v
,
C
)
var
t
uint64
t
,
u
,
v
=
madd2sb
(
x
[
3
],
x
[
4
],
p
[
4
],
u
)
C
,
p
[
3
]
=
madd2
(
m
,
5412103778470702295
,
v
,
C
)
_
,
u
,
v
=
madd2s
(
x
[
3
],
x
[
5
],
p
[
5
],
t
,
u
)
p
[
5
],
p
[
4
]
=
madd3
(
m
,
1873798617647539866
,
v
,
C
,
u
)
}
{
// round 4
m
:=
p
[
0
]
*
9940570264628428797
C
:=
madd0
(
m
,
13402431016077863595
,
p
[
0
])
C
,
p
[
0
]
=
madd2
(
m
,
2210141511517208575
,
p
[
1
],
C
)
C
,
p
[
1
]
=
madd2
(
m
,
7435674573564081700
,
p
[
2
],
C
)
C
,
p
[
2
]
=
madd2
(
m
,
7239337960414712511
,
p
[
3
],
C
)
u
,
v
=
madd1
(
x
[
4
],
x
[
4
],
p
[
4
])
C
,
p
[
3
]
=
madd2
(
m
,
5412103778470702295
,
v
,
C
)
_
,
u
,
v
=
madd2sb
(
x
[
4
],
x
[
5
],
p
[
5
],
u
)
p
[
5
],
p
[
4
]
=
madd3
(
m
,
1873798617647539866
,
v
,
C
,
u
)
}
{
// round 5
m
:=
p
[
0
]
*
9940570264628428797
C
:=
madd0
(
m
,
13402431016077863595
,
p
[
0
])
C
,
z
[
0
]
=
madd2
(
m
,
2210141511517208575
,
p
[
1
],
C
)
C
,
z
[
1
]
=
madd2
(
m
,
7435674573564081700
,
p
[
2
],
C
)
C
,
z
[
2
]
=
madd2
(
m
,
7239337960414712511
,
p
[
3
],
C
)
C
,
z
[
3
]
=
madd2
(
m
,
5412103778470702295
,
p
[
4
],
C
)
u
,
v
=
madd1
(
x
[
5
],
x
[
5
],
p
[
5
])
z
[
5
],
z
[
4
]
=
madd3
(
m
,
1873798617647539866
,
v
,
C
,
u
)
}
// if z > q --> z -= q
// note: this is NOT constant time
if
!
(
z
[
5
]
<
1873798617647539866
||
(
z
[
5
]
==
1873798617647539866
&&
(
z
[
4
]
<
5412103778470702295
||
(
z
[
4
]
==
5412103778470702295
&&
(
z
[
3
]
<
7239337960414712511
||
(
z
[
3
]
==
7239337960414712511
&&
(
z
[
2
]
<
7435674573564081700
||
(
z
[
2
]
==
7435674573564081700
&&
(
z
[
1
]
<
2210141511517208575
||
(
z
[
1
]
==
2210141511517208575
&&
(
z
[
0
]
<
13402431016077863595
)))))))))))
{
var
b
uint64
z
[
0
],
b
=
bits
.
Sub64
(
z
[
0
],
13402431016077863595
,
0
)
z
[
1
],
b
=
bits
.
Sub64
(
z
[
1
],
2210141511517208575
,
b
)
z
[
2
],
b
=
bits
.
Sub64
(
z
[
2
],
7435674573564081700
,
b
)
z
[
3
],
b
=
bits
.
Sub64
(
z
[
3
],
7239337960414712511
,
b
)
z
[
4
],
b
=
bits
.
Sub64
(
z
[
4
],
5412103778470702295
,
b
)
z
[
5
],
_
=
bits
.
Sub64
(
z
[
5
],
1873798617647539866
,
b
)
}
}
// arith.go
// Copyright 2020 ConsenSys AG
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by goff DO NOT EDIT
func
madd
(
a
,
b
,
t
,
u
,
v
uint64
)
(
uint64
,
uint64
,
uint64
)
{
var
carry
uint64
hi
,
lo
:=
bits
.
Mul64
(
a
,
b
)
v
,
carry
=
bits
.
Add64
(
lo
,
v
,
0
)
u
,
carry
=
bits
.
Add64
(
hi
,
u
,
carry
)
t
,
_
=
bits
.
Add64
(
t
,
0
,
carry
)
return
t
,
u
,
v
}
// madd0 hi = a*b + c (discards lo bits)
func
madd0
(
a
,
b
,
c
uint64
)
(
hi
uint64
)
{
var
carry
,
lo
uint64
hi
,
lo
=
bits
.
Mul64
(
a
,
b
)
_
,
carry
=
bits
.
Add64
(
lo
,
c
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
return
}
// madd1 hi, lo = a*b + c
func
madd1
(
a
,
b
,
c
uint64
)
(
hi
uint64
,
lo
uint64
)
{
var
carry
uint64
hi
,
lo
=
bits
.
Mul64
(
a
,
b
)
lo
,
carry
=
bits
.
Add64
(
lo
,
c
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
return
}
// madd2 hi, lo = a*b + c + d
func
madd2
(
a
,
b
,
c
,
d
uint64
)
(
hi
uint64
,
lo
uint64
)
{
var
carry
uint64
hi
,
lo
=
bits
.
Mul64
(
a
,
b
)
c
,
carry
=
bits
.
Add64
(
c
,
d
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
lo
,
carry
=
bits
.
Add64
(
lo
,
c
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
return
}
// madd2s superhi, hi, lo = 2*a*b + c + d + e
func
madd2s
(
a
,
b
,
c
,
d
,
e
uint64
)
(
superhi
,
hi
,
lo
uint64
)
{
var
carry
,
sum
uint64
hi
,
lo
=
bits
.
Mul64
(
a
,
b
)
lo
,
carry
=
bits
.
Add64
(
lo
,
lo
,
0
)
hi
,
superhi
=
bits
.
Add64
(
hi
,
hi
,
carry
)
sum
,
carry
=
bits
.
Add64
(
c
,
e
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
lo
,
carry
=
bits
.
Add64
(
lo
,
sum
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
d
)
return
}
func
madd1s
(
a
,
b
,
d
,
e
uint64
)
(
superhi
,
hi
,
lo
uint64
)
{
var
carry
uint64
hi
,
lo
=
bits
.
Mul64
(
a
,
b
)
lo
,
carry
=
bits
.
Add64
(
lo
,
lo
,
0
)
hi
,
superhi
=
bits
.
Add64
(
hi
,
hi
,
carry
)
lo
,
carry
=
bits
.
Add64
(
lo
,
e
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
d
)
return
}
func
madd2sb
(
a
,
b
,
c
,
e
uint64
)
(
superhi
,
hi
,
lo
uint64
)
{
var
carry
,
sum
uint64
hi
,
lo
=
bits
.
Mul64
(
a
,
b
)
lo
,
carry
=
bits
.
Add64
(
lo
,
lo
,
0
)
hi
,
superhi
=
bits
.
Add64
(
hi
,
hi
,
carry
)
sum
,
carry
=
bits
.
Add64
(
c
,
e
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
lo
,
carry
=
bits
.
Add64
(
lo
,
sum
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
return
}
func
madd1sb
(
a
,
b
,
e
uint64
)
(
superhi
,
hi
,
lo
uint64
)
{
var
carry
uint64
hi
,
lo
=
bits
.
Mul64
(
a
,
b
)
lo
,
carry
=
bits
.
Add64
(
lo
,
lo
,
0
)
hi
,
superhi
=
bits
.
Add64
(
hi
,
hi
,
carry
)
lo
,
carry
=
bits
.
Add64
(
lo
,
e
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
return
}
func
madd3
(
a
,
b
,
c
,
d
,
e
uint64
)
(
hi
uint64
,
lo
uint64
)
{
var
carry
uint64
hi
,
lo
=
bits
.
Mul64
(
a
,
b
)
c
,
carry
=
bits
.
Add64
(
c
,
d
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
0
,
carry
)
lo
,
carry
=
bits
.
Add64
(
lo
,
c
,
0
)
hi
,
_
=
bits
.
Add64
(
hi
,
e
,
carry
)
return
}
minigeth/crypto/bls12381/bls12_381.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
/*
Field Constants
*/
// Base field modulus
// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
// Size of six words
// r = 2 ^ 384
// modulus = p
var
modulus
=
fe
{
0xb9feffffffffaaab
,
0x1eabfffeb153ffff
,
0x6730d2a0f6b0f624
,
0x64774b84f38512bf
,
0x4b1ba7b6434bacd7
,
0x1a0111ea397fe69a
}
var
(
// -p^(-1) mod 2^64
inp
uint64
=
0x89f3fffcfffcfffd
// This value is used in assembly code
_
=
inp
)
// r mod p
var
r1
=
&
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
}
// r^2 mod p
var
r2
=
&
fe
{
0xf4df1f341c341746
,
0x0a76e6a609d104f1
,
0x8de5476c4c95b6d5
,
0x67eb88a9939d83c0
,
0x9a793e85b519952d
,
0x11988fe592cae3aa
,
}
// -1 + 0 * u
var
negativeOne2
=
&
fe2
{
fe
{
0x43f5fffffffcaaae
,
0x32b7fff2ed47fffd
,
0x07e83a49a2e99d69
,
0xeca8f3318332bb7a
,
0xef148d1ea0f4c069
,
0x040ab3263eff0206
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
}
// 2 ^ (-1)
var
twoInv
=
&
fe
{
0x1804000000015554
,
0x855000053ab00001
,
0x633cb57c253c276f
,
0x6e22d1ec31ebb502
,
0xd3916126f2d14ca2
,
0x17fbb8571a006596
}
// (p - 3) / 4
var
pMinus3Over4
=
bigFromHex
(
"0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaaa"
)
// (p + 1) / 4
var
pPlus1Over4
=
bigFromHex
(
"0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaab"
)
// (p - 1) / 2
var
pMinus1Over2
=
bigFromHex
(
"0xd0088f51cbff34d258dd3db21a5d66bb23ba5c279c2895fb39869507b587b120f55ffff58a9ffffdcff7fffffffd555"
)
// -1
var
nonResidue1
=
&
fe
{
0x43f5fffffffcaaae
,
0x32b7fff2ed47fffd
,
0x07e83a49a2e99d69
,
0xeca8f3318332bb7a
,
0xef148d1ea0f4c069
,
0x040ab3263eff0206
}
// (1 + 1 * u)
var
nonResidue2
=
&
fe2
{
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
}
/*
Curve Constants
*/
// b coefficient for G1
var
b
=
&
fe
{
0xaa270000000cfff3
,
0x53cc0032fc34000a
,
0x478fe97a6b0a807f
,
0xb1d37ebee6ba24d7
,
0x8ec9733bbf78ab2f
,
0x09d645513d83de7e
}
// b coefficient for G2
var
b2
=
&
fe2
{
fe
{
0xaa270000000cfff3
,
0x53cc0032fc34000a
,
0x478fe97a6b0a807f
,
0xb1d37ebee6ba24d7
,
0x8ec9733bbf78ab2f
,
0x09d645513d83de7e
},
fe
{
0xaa270000000cfff3
,
0x53cc0032fc34000a
,
0x478fe97a6b0a807f
,
0xb1d37ebee6ba24d7
,
0x8ec9733bbf78ab2f
,
0x09d645513d83de7e
},
}
// Curve order
var
q
=
bigFromHex
(
"0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"
)
// Efficient cofactor of G1
var
cofactorEFFG1
=
bigFromHex
(
"0xd201000000010001"
)
// Efficient cofactor of G2
var
cofactorEFFG2
=
bigFromHex
(
"0x0bc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551"
)
var
g1One
=
PointG1
{
fe
{
0x5cb38790fd530c16
,
0x7817fc679976fff5
,
0x154f95c7143ba1c1
,
0xf0ae6acdf3d0e747
,
0xedce6ecc21dbf440
,
0x120177419e0bfb75
},
fe
{
0xbaac93d50ce72271
,
0x8c22631a7918fd8e
,
0xdd595f13570725ce
,
0x51ac582950405194
,
0x0e1c8c3fad0059c0
,
0x0bbc3efc5008a26a
},
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
}
var
g2One
=
PointG2
{
fe2
{
fe
{
0xf5f28fa202940a10
,
0xb3f5fb2687b4961a
,
0xa1a893b53e2ae580
,
0x9894999d1a3caee9
,
0x6f67b7631863366b
,
0x058191924350bcd7
},
fe
{
0xa5a9c0759e23f606
,
0xaaa0c59dbccd60c3
,
0x3bb17e18e2867806
,
0x1b1ab6cc8541b367
,
0xc2b6ed0ef2158547
,
0x11922a097360edf3
},
},
fe2
{
fe
{
0x4c730af860494c4a
,
0x597cfa1f5e369c5a
,
0xe7e6856caa0a635a
,
0xbbefb5e96e0d495f
,
0x07d3a975f0ef25a2
,
0x083fd8e7e80dae5
},
fe
{
0xadc0fc92df64b05d
,
0x18aa270a2b1461dc
,
0x86adac6a3be4eba0
,
0x79495c4ec93da33a
,
0xe7175850a43ccaed
,
0xb2bc2a163de1bf2
},
},
fe2
{
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
}
/*
Frobenious Coeffs
*/
var
frobeniusCoeffs61
=
[
6
]
fe2
{
fe2
{
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
fe
{
0xcd03c9e48671f071
,
0x5dab22461fcda5d2
,
0x587042afd3851b95
,
0x8eb60ebe01bacb9e
,
0x03f97d6e83d050d2
,
0x18f0206554638741
},
},
fe2
{
fe
{
0x30f1361b798a64e8
,
0xf3b8ddab7ece5a2a
,
0x16a8ca3ac61577f7
,
0xc26a2ff874fd029b
,
0x3636b76660701c6e
,
0x051ba4ab241b6160
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
},
fe2
{
fe
{
0xcd03c9e48671f071
,
0x5dab22461fcda5d2
,
0x587042afd3851b95
,
0x8eb60ebe01bacb9e
,
0x03f97d6e83d050d2
,
0x18f0206554638741
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
fe
{
0x30f1361b798a64e8
,
0xf3b8ddab7ece5a2a
,
0x16a8ca3ac61577f7
,
0xc26a2ff874fd029b
,
0x3636b76660701c6e
,
0x051ba4ab241b6160
},
},
}
var
frobeniusCoeffs62
=
[
6
]
fe2
{
fe2
{
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x890dc9e4867545c3
,
0x2af322533285a5d5
,
0x50880866309b7e2c
,
0xa20d1b8c7e881024
,
0x14e4f04fe2db9068
,
0x14e56d3f1564853a
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0xcd03c9e48671f071
,
0x5dab22461fcda5d2
,
0x587042afd3851b95
,
0x8eb60ebe01bacb9e
,
0x03f97d6e83d050d2
,
0x18f0206554638741
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x43f5fffffffcaaae
,
0x32b7fff2ed47fffd
,
0x07e83a49a2e99d69
,
0xeca8f3318332bb7a
,
0xef148d1ea0f4c069
,
0x040ab3263eff0206
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x30f1361b798a64e8
,
0xf3b8ddab7ece5a2a
,
0x16a8ca3ac61577f7
,
0xc26a2ff874fd029b
,
0x3636b76660701c6e
,
0x051ba4ab241b6160
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0xecfb361b798dba3a
,
0xc100ddb891865a2c
,
0x0ec08ff1232bda8e
,
0xd5c13cc6f1ca4721
,
0x47222a47bf7b5c04
,
0x0110f184e51c5f59
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
}
var
frobeniusCoeffs12
=
[
12
]
fe2
{
fe2
{
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x07089552b319d465
,
0xc6695f92b50a8313
,
0x97e83cccd117228f
,
0xa35baecab2dc29ee
,
0x1ce393ea5daace4d
,
0x08f2220fb0fb66eb
},
fe
{
0xb2f66aad4ce5d646
,
0x5842a06bfc497cec
,
0xcf4895d42599d394
,
0xc11b9cba40a8e8d0
,
0x2e3813cbe5a0de89
,
0x110eefda88847faf
},
},
fe2
{
fe
{
0xecfb361b798dba3a
,
0xc100ddb891865a2c
,
0x0ec08ff1232bda8e
,
0xd5c13cc6f1ca4721
,
0x47222a47bf7b5c04
,
0x0110f184e51c5f59
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x3e2f585da55c9ad1
,
0x4294213d86c18183
,
0x382844c88b623732
,
0x92ad2afd19103e18
,
0x1d794e4fac7cf0b9
,
0x0bd592fc7d825ec8
},
fe
{
0x7bcfa7a25aa30fda
,
0xdc17dec12a927e7c
,
0x2f088dd86b4ebef1
,
0xd1ca2087da74d4a7
,
0x2da2596696cebc1d
,
0x0e2b7eedbbfd87d2
},
},
fe2
{
fe
{
0x30f1361b798a64e8
,
0xf3b8ddab7ece5a2a
,
0x16a8ca3ac61577f7
,
0xc26a2ff874fd029b
,
0x3636b76660701c6e
,
0x051ba4ab241b6160
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x3726c30af242c66c
,
0x7c2ac1aad1b6fe70
,
0xa04007fbba4b14a2
,
0xef517c3266341429
,
0x0095ba654ed2226b
,
0x02e370eccc86f7dd
},
fe
{
0x82d83cf50dbce43f
,
0xa2813e53df9d018f
,
0xc6f0caa53c65e181
,
0x7525cf528d50fe95
,
0x4a85ed50f4798a6b
,
0x171da0fd6cf8eebd
},
},
fe2
{
fe
{
0x43f5fffffffcaaae
,
0x32b7fff2ed47fffd
,
0x07e83a49a2e99d69
,
0xeca8f3318332bb7a
,
0xef148d1ea0f4c069
,
0x040ab3263eff0206
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0xb2f66aad4ce5d646
,
0x5842a06bfc497cec
,
0xcf4895d42599d394
,
0xc11b9cba40a8e8d0
,
0x2e3813cbe5a0de89
,
0x110eefda88847faf
},
fe
{
0x07089552b319d465
,
0xc6695f92b50a8313
,
0x97e83cccd117228f
,
0xa35baecab2dc29ee
,
0x1ce393ea5daace4d
,
0x08f2220fb0fb66eb
},
},
fe2
{
fe
{
0xcd03c9e48671f071
,
0x5dab22461fcda5d2
,
0x587042afd3851b95
,
0x8eb60ebe01bacb9e
,
0x03f97d6e83d050d2
,
0x18f0206554638741
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x7bcfa7a25aa30fda
,
0xdc17dec12a927e7c
,
0x2f088dd86b4ebef1
,
0xd1ca2087da74d4a7
,
0x2da2596696cebc1d
,
0x0e2b7eedbbfd87d2
},
fe
{
0x3e2f585da55c9ad1
,
0x4294213d86c18183
,
0x382844c88b623732
,
0x92ad2afd19103e18
,
0x1d794e4fac7cf0b9
,
0x0bd592fc7d825ec8
},
},
fe2
{
fe
{
0x890dc9e4867545c3
,
0x2af322533285a5d5
,
0x50880866309b7e2c
,
0xa20d1b8c7e881024
,
0x14e4f04fe2db9068
,
0x14e56d3f1564853a
},
fe
{
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
,
0x0000000000000000
},
},
fe2
{
fe
{
0x82d83cf50dbce43f
,
0xa2813e53df9d018f
,
0xc6f0caa53c65e181
,
0x7525cf528d50fe95
,
0x4a85ed50f4798a6b
,
0x171da0fd6cf8eebd
},
fe
{
0x3726c30af242c66c
,
0x7c2ac1aad1b6fe70
,
0xa04007fbba4b14a2
,
0xef517c3266341429
,
0x0095ba654ed2226b
,
0x02e370eccc86f7dd
},
},
}
/*
x
*/
var
x
=
bigFromHex
(
"0xd201000000010000"
)
minigeth/crypto/bls12381/field_element.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"crypto/rand"
"encoding/hex"
"fmt"
"io"
"math/big"
)
// fe is base field element representation
type
fe
[
6
]
uint64
// fe2 is element representation of 'fp2' which is quadratic extension of base field 'fp'
// Representation follows c[0] + c[1] * u encoding order.
type
fe2
[
2
]
fe
// fe6 is element representation of 'fp6' field which is cubic extension of 'fp2'
// Representation follows c[0] + c[1] * v + c[2] * v^2 encoding order.
type
fe6
[
3
]
fe2
// fe12 is element representation of 'fp12' field which is quadratic extension of 'fp6'
// Representation follows c[0] + c[1] * w encoding order.
type
fe12
[
2
]
fe6
func
(
fe
*
fe
)
setBytes
(
in
[]
byte
)
*
fe
{
size
:=
48
l
:=
len
(
in
)
if
l
>=
size
{
l
=
size
}
padded
:=
make
([]
byte
,
size
)
copy
(
padded
[
size
-
l
:
],
in
[
:
])
var
a
int
for
i
:=
0
;
i
<
6
;
i
++
{
a
=
size
-
i
*
8
fe
[
i
]
=
uint64
(
padded
[
a
-
1
])
|
uint64
(
padded
[
a
-
2
])
<<
8
|
uint64
(
padded
[
a
-
3
])
<<
16
|
uint64
(
padded
[
a
-
4
])
<<
24
|
uint64
(
padded
[
a
-
5
])
<<
32
|
uint64
(
padded
[
a
-
6
])
<<
40
|
uint64
(
padded
[
a
-
7
])
<<
48
|
uint64
(
padded
[
a
-
8
])
<<
56
}
return
fe
}
func
(
fe
*
fe
)
setBig
(
a
*
big
.
Int
)
*
fe
{
return
fe
.
setBytes
(
a
.
Bytes
())
}
func
(
fe
*
fe
)
setString
(
s
string
)
(
*
fe
,
error
)
{
if
s
[
:
2
]
==
"0x"
{
s
=
s
[
2
:
]
}
bytes
,
err
:=
hex
.
DecodeString
(
s
)
if
err
!=
nil
{
return
nil
,
err
}
return
fe
.
setBytes
(
bytes
),
nil
}
func
(
fe
*
fe
)
set
(
fe2
*
fe
)
*
fe
{
fe
[
0
]
=
fe2
[
0
]
fe
[
1
]
=
fe2
[
1
]
fe
[
2
]
=
fe2
[
2
]
fe
[
3
]
=
fe2
[
3
]
fe
[
4
]
=
fe2
[
4
]
fe
[
5
]
=
fe2
[
5
]
return
fe
}
func
(
fe
*
fe
)
bytes
()
[]
byte
{
out
:=
make
([]
byte
,
48
)
var
a
int
for
i
:=
0
;
i
<
6
;
i
++
{
a
=
48
-
i
*
8
out
[
a
-
1
]
=
byte
(
fe
[
i
])
out
[
a
-
2
]
=
byte
(
fe
[
i
]
>>
8
)
out
[
a
-
3
]
=
byte
(
fe
[
i
]
>>
16
)
out
[
a
-
4
]
=
byte
(
fe
[
i
]
>>
24
)
out
[
a
-
5
]
=
byte
(
fe
[
i
]
>>
32
)
out
[
a
-
6
]
=
byte
(
fe
[
i
]
>>
40
)
out
[
a
-
7
]
=
byte
(
fe
[
i
]
>>
48
)
out
[
a
-
8
]
=
byte
(
fe
[
i
]
>>
56
)
}
return
out
}
func
(
fe
*
fe
)
big
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
SetBytes
(
fe
.
bytes
())
}
func
(
fe
*
fe
)
string
()
(
s
string
)
{
for
i
:=
5
;
i
>=
0
;
i
--
{
s
=
fmt
.
Sprintf
(
"%s%16.16x"
,
s
,
fe
[
i
])
}
return
"0x"
+
s
}
func
(
fe
*
fe
)
zero
()
*
fe
{
fe
[
0
]
=
0
fe
[
1
]
=
0
fe
[
2
]
=
0
fe
[
3
]
=
0
fe
[
4
]
=
0
fe
[
5
]
=
0
return
fe
}
func
(
fe
*
fe
)
one
()
*
fe
{
return
fe
.
set
(
r1
)
}
func
(
fe
*
fe
)
rand
(
r
io
.
Reader
)
(
*
fe
,
error
)
{
bi
,
err
:=
rand
.
Int
(
r
,
modulus
.
big
())
if
err
!=
nil
{
return
nil
,
err
}
return
fe
.
setBig
(
bi
),
nil
}
func
(
fe
*
fe
)
isValid
()
bool
{
return
fe
.
cmp
(
&
modulus
)
<
0
}
func
(
fe
*
fe
)
isOdd
()
bool
{
var
mask
uint64
=
1
return
fe
[
0
]
&
mask
!=
0
}
func
(
fe
*
fe
)
isEven
()
bool
{
var
mask
uint64
=
1
return
fe
[
0
]
&
mask
==
0
}
func
(
fe
*
fe
)
isZero
()
bool
{
return
(
fe
[
5
]
|
fe
[
4
]
|
fe
[
3
]
|
fe
[
2
]
|
fe
[
1
]
|
fe
[
0
])
==
0
}
func
(
fe
*
fe
)
isOne
()
bool
{
return
fe
.
equal
(
r1
)
}
func
(
fe
*
fe
)
cmp
(
fe2
*
fe
)
int
{
for
i
:=
5
;
i
>=
0
;
i
--
{
if
fe
[
i
]
>
fe2
[
i
]
{
return
1
}
else
if
fe
[
i
]
<
fe2
[
i
]
{
return
-
1
}
}
return
0
}
func
(
fe
*
fe
)
equal
(
fe2
*
fe
)
bool
{
return
fe2
[
0
]
==
fe
[
0
]
&&
fe2
[
1
]
==
fe
[
1
]
&&
fe2
[
2
]
==
fe
[
2
]
&&
fe2
[
3
]
==
fe
[
3
]
&&
fe2
[
4
]
==
fe
[
4
]
&&
fe2
[
5
]
==
fe
[
5
]
}
func
(
e
*
fe
)
sign
()
bool
{
r
:=
new
(
fe
)
fromMont
(
r
,
e
)
return
r
[
0
]
&
1
==
0
}
func
(
fe
*
fe
)
div2
(
e
uint64
)
{
fe
[
0
]
=
fe
[
0
]
>>
1
|
fe
[
1
]
<<
63
fe
[
1
]
=
fe
[
1
]
>>
1
|
fe
[
2
]
<<
63
fe
[
2
]
=
fe
[
2
]
>>
1
|
fe
[
3
]
<<
63
fe
[
3
]
=
fe
[
3
]
>>
1
|
fe
[
4
]
<<
63
fe
[
4
]
=
fe
[
4
]
>>
1
|
fe
[
5
]
<<
63
fe
[
5
]
=
fe
[
5
]
>>
1
|
e
<<
63
}
func
(
fe
*
fe
)
mul2
()
uint64
{
e
:=
fe
[
5
]
>>
63
fe
[
5
]
=
fe
[
5
]
<<
1
|
fe
[
4
]
>>
63
fe
[
4
]
=
fe
[
4
]
<<
1
|
fe
[
3
]
>>
63
fe
[
3
]
=
fe
[
3
]
<<
1
|
fe
[
2
]
>>
63
fe
[
2
]
=
fe
[
2
]
<<
1
|
fe
[
1
]
>>
63
fe
[
1
]
=
fe
[
1
]
<<
1
|
fe
[
0
]
>>
63
fe
[
0
]
=
fe
[
0
]
<<
1
return
e
}
func
(
e
*
fe2
)
zero
()
*
fe2
{
e
[
0
]
.
zero
()
e
[
1
]
.
zero
()
return
e
}
func
(
e
*
fe2
)
one
()
*
fe2
{
e
[
0
]
.
one
()
e
[
1
]
.
zero
()
return
e
}
func
(
e
*
fe2
)
set
(
e2
*
fe2
)
*
fe2
{
e
[
0
]
.
set
(
&
e2
[
0
])
e
[
1
]
.
set
(
&
e2
[
1
])
return
e
}
func
(
e
*
fe2
)
rand
(
r
io
.
Reader
)
(
*
fe2
,
error
)
{
a0
,
err
:=
new
(
fe
)
.
rand
(
r
)
if
err
!=
nil
{
return
nil
,
err
}
a1
,
err
:=
new
(
fe
)
.
rand
(
r
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
fe2
{
*
a0
,
*
a1
},
nil
}
func
(
e
*
fe2
)
isOne
()
bool
{
return
e
[
0
]
.
isOne
()
&&
e
[
1
]
.
isZero
()
}
func
(
e
*
fe2
)
isZero
()
bool
{
return
e
[
0
]
.
isZero
()
&&
e
[
1
]
.
isZero
()
}
func
(
e
*
fe2
)
equal
(
e2
*
fe2
)
bool
{
return
e
[
0
]
.
equal
(
&
e2
[
0
])
&&
e
[
1
]
.
equal
(
&
e2
[
1
])
}
func
(
e
*
fe2
)
sign
()
bool
{
r
:=
new
(
fe
)
if
!
e
[
0
]
.
isZero
()
{
fromMont
(
r
,
&
e
[
0
])
return
r
[
0
]
&
1
==
0
}
fromMont
(
r
,
&
e
[
1
])
return
r
[
0
]
&
1
==
0
}
func
(
e
*
fe6
)
zero
()
*
fe6
{
e
[
0
]
.
zero
()
e
[
1
]
.
zero
()
e
[
2
]
.
zero
()
return
e
}
func
(
e
*
fe6
)
one
()
*
fe6
{
e
[
0
]
.
one
()
e
[
1
]
.
zero
()
e
[
2
]
.
zero
()
return
e
}
func
(
e
*
fe6
)
set
(
e2
*
fe6
)
*
fe6
{
e
[
0
]
.
set
(
&
e2
[
0
])
e
[
1
]
.
set
(
&
e2
[
1
])
e
[
2
]
.
set
(
&
e2
[
2
])
return
e
}
func
(
e
*
fe6
)
rand
(
r
io
.
Reader
)
(
*
fe6
,
error
)
{
a0
,
err
:=
new
(
fe2
)
.
rand
(
r
)
if
err
!=
nil
{
return
nil
,
err
}
a1
,
err
:=
new
(
fe2
)
.
rand
(
r
)
if
err
!=
nil
{
return
nil
,
err
}
a2
,
err
:=
new
(
fe2
)
.
rand
(
r
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
fe6
{
*
a0
,
*
a1
,
*
a2
},
nil
}
func
(
e
*
fe6
)
isOne
()
bool
{
return
e
[
0
]
.
isOne
()
&&
e
[
1
]
.
isZero
()
&&
e
[
2
]
.
isZero
()
}
func
(
e
*
fe6
)
isZero
()
bool
{
return
e
[
0
]
.
isZero
()
&&
e
[
1
]
.
isZero
()
&&
e
[
2
]
.
isZero
()
}
func
(
e
*
fe6
)
equal
(
e2
*
fe6
)
bool
{
return
e
[
0
]
.
equal
(
&
e2
[
0
])
&&
e
[
1
]
.
equal
(
&
e2
[
1
])
&&
e
[
2
]
.
equal
(
&
e2
[
2
])
}
func
(
e
*
fe12
)
zero
()
*
fe12
{
e
[
0
]
.
zero
()
e
[
1
]
.
zero
()
return
e
}
func
(
e
*
fe12
)
one
()
*
fe12
{
e
[
0
]
.
one
()
e
[
1
]
.
zero
()
return
e
}
func
(
e
*
fe12
)
set
(
e2
*
fe12
)
*
fe12
{
e
[
0
]
.
set
(
&
e2
[
0
])
e
[
1
]
.
set
(
&
e2
[
1
])
return
e
}
func
(
e
*
fe12
)
rand
(
r
io
.
Reader
)
(
*
fe12
,
error
)
{
a0
,
err
:=
new
(
fe6
)
.
rand
(
r
)
if
err
!=
nil
{
return
nil
,
err
}
a1
,
err
:=
new
(
fe6
)
.
rand
(
r
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
fe12
{
*
a0
,
*
a1
},
nil
}
func
(
e
*
fe12
)
isOne
()
bool
{
return
e
[
0
]
.
isOne
()
&&
e
[
1
]
.
isZero
()
}
func
(
e
*
fe12
)
isZero
()
bool
{
return
e
[
0
]
.
isZero
()
&&
e
[
1
]
.
isZero
()
}
func
(
e
*
fe12
)
equal
(
e2
*
fe12
)
bool
{
return
e
[
0
]
.
equal
(
&
e2
[
0
])
&&
e
[
1
]
.
equal
(
&
e2
[
1
])
}
minigeth/crypto/bls12381/fp.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"errors"
"math/big"
)
func
fromBytes
(
in
[]
byte
)
(
*
fe
,
error
)
{
fe
:=
&
fe
{}
if
len
(
in
)
!=
48
{
return
nil
,
errors
.
New
(
"input string should be equal 48 bytes"
)
}
fe
.
setBytes
(
in
)
if
!
fe
.
isValid
()
{
return
nil
,
errors
.
New
(
"must be less than modulus"
)
}
toMont
(
fe
,
fe
)
return
fe
,
nil
}
func
fromBig
(
in
*
big
.
Int
)
(
*
fe
,
error
)
{
fe
:=
new
(
fe
)
.
setBig
(
in
)
if
!
fe
.
isValid
()
{
return
nil
,
errors
.
New
(
"invalid input string"
)
}
toMont
(
fe
,
fe
)
return
fe
,
nil
}
func
fromString
(
in
string
)
(
*
fe
,
error
)
{
fe
,
err
:=
new
(
fe
)
.
setString
(
in
)
if
err
!=
nil
{
return
nil
,
err
}
if
!
fe
.
isValid
()
{
return
nil
,
errors
.
New
(
"invalid input string"
)
}
toMont
(
fe
,
fe
)
return
fe
,
nil
}
func
toBytes
(
e
*
fe
)
[]
byte
{
e2
:=
new
(
fe
)
fromMont
(
e2
,
e
)
return
e2
.
bytes
()
}
func
toBig
(
e
*
fe
)
*
big
.
Int
{
e2
:=
new
(
fe
)
fromMont
(
e2
,
e
)
return
e2
.
big
()
}
func
toString
(
e
*
fe
)
(
s
string
)
{
e2
:=
new
(
fe
)
fromMont
(
e2
,
e
)
return
e2
.
string
()
}
func
toMont
(
c
,
a
*
fe
)
{
mul
(
c
,
a
,
r2
)
}
func
fromMont
(
c
,
a
*
fe
)
{
mul
(
c
,
a
,
&
fe
{
1
})
}
func
exp
(
c
,
a
*
fe
,
e
*
big
.
Int
)
{
z
:=
new
(
fe
)
.
set
(
r1
)
for
i
:=
e
.
BitLen
();
i
>=
0
;
i
--
{
mul
(
z
,
z
,
z
)
if
e
.
Bit
(
i
)
==
1
{
mul
(
z
,
z
,
a
)
}
}
c
.
set
(
z
)
}
func
inverse
(
inv
,
e
*
fe
)
{
if
e
.
isZero
()
{
inv
.
zero
()
return
}
u
:=
new
(
fe
)
.
set
(
&
modulus
)
v
:=
new
(
fe
)
.
set
(
e
)
s
:=
&
fe
{
1
}
r
:=
&
fe
{
0
}
var
k
int
var
z
uint64
var
found
=
false
// Phase 1
for
i
:=
0
;
i
<
768
;
i
++
{
if
v
.
isZero
()
{
found
=
true
break
}
if
u
.
isEven
()
{
u
.
div2
(
0
)
s
.
mul2
()
}
else
if
v
.
isEven
()
{
v
.
div2
(
0
)
z
+=
r
.
mul2
()
}
else
if
u
.
cmp
(
v
)
==
1
{
lsubAssign
(
u
,
v
)
u
.
div2
(
0
)
laddAssign
(
r
,
s
)
s
.
mul2
()
}
else
{
lsubAssign
(
v
,
u
)
v
.
div2
(
0
)
laddAssign
(
s
,
r
)
z
+=
r
.
mul2
()
}
k
+=
1
}
if
!
found
{
inv
.
zero
()
return
}
if
k
<
381
||
k
>
381
+
384
{
inv
.
zero
()
return
}
if
r
.
cmp
(
&
modulus
)
!=
-
1
||
z
>
0
{
lsubAssign
(
r
,
&
modulus
)
}
u
.
set
(
&
modulus
)
lsubAssign
(
u
,
r
)
// Phase 2
for
i
:=
k
;
i
<
384
*
2
;
i
++
{
double
(
u
,
u
)
}
inv
.
set
(
u
)
}
func
sqrt
(
c
,
a
*
fe
)
bool
{
u
,
v
:=
new
(
fe
)
.
set
(
a
),
new
(
fe
)
exp
(
c
,
a
,
pPlus1Over4
)
square
(
v
,
c
)
return
u
.
equal
(
v
)
}
func
isQuadraticNonResidue
(
elem
*
fe
)
bool
{
result
:=
new
(
fe
)
exp
(
result
,
elem
,
pMinus1Over2
)
return
!
result
.
isOne
()
}
minigeth/crypto/bls12381/fp12.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"errors"
"math/big"
)
type
fp12
struct
{
fp12temp
fp6
*
fp6
}
type
fp12temp
struct
{
t2
[
9
]
*
fe2
t6
[
5
]
*
fe6
t12
*
fe12
}
func
newFp12Temp
()
fp12temp
{
t2
:=
[
9
]
*
fe2
{}
t6
:=
[
5
]
*
fe6
{}
for
i
:=
0
;
i
<
len
(
t2
);
i
++
{
t2
[
i
]
=
&
fe2
{}
}
for
i
:=
0
;
i
<
len
(
t6
);
i
++
{
t6
[
i
]
=
&
fe6
{}
}
return
fp12temp
{
t2
,
t6
,
&
fe12
{}}
}
func
newFp12
(
fp6
*
fp6
)
*
fp12
{
t
:=
newFp12Temp
()
if
fp6
==
nil
{
return
&
fp12
{
t
,
newFp6
(
nil
)}
}
return
&
fp12
{
t
,
fp6
}
}
func
(
e
*
fp12
)
fp2
()
*
fp2
{
return
e
.
fp6
.
fp2
}
func
(
e
*
fp12
)
fromBytes
(
in
[]
byte
)
(
*
fe12
,
error
)
{
if
len
(
in
)
!=
576
{
return
nil
,
errors
.
New
(
"input string should be larger than 96 bytes"
)
}
fp6
:=
e
.
fp6
c1
,
err
:=
fp6
.
fromBytes
(
in
[
:
288
])
if
err
!=
nil
{
return
nil
,
err
}
c0
,
err
:=
fp6
.
fromBytes
(
in
[
288
:
])
if
err
!=
nil
{
return
nil
,
err
}
return
&
fe12
{
*
c0
,
*
c1
},
nil
}
func
(
e
*
fp12
)
toBytes
(
a
*
fe12
)
[]
byte
{
fp6
:=
e
.
fp6
out
:=
make
([]
byte
,
576
)
copy
(
out
[
:
288
],
fp6
.
toBytes
(
&
a
[
1
]))
copy
(
out
[
288
:
],
fp6
.
toBytes
(
&
a
[
0
]))
return
out
}
func
(
e
*
fp12
)
new
()
*
fe12
{
return
new
(
fe12
)
}
func
(
e
*
fp12
)
zero
()
*
fe12
{
return
new
(
fe12
)
}
func
(
e
*
fp12
)
one
()
*
fe12
{
return
new
(
fe12
)
.
one
()
}
func
(
e
*
fp12
)
add
(
c
,
a
,
b
*
fe12
)
{
fp6
:=
e
.
fp6
fp6
.
add
(
&
c
[
0
],
&
a
[
0
],
&
b
[
0
])
fp6
.
add
(
&
c
[
1
],
&
a
[
1
],
&
b
[
1
])
}
func
(
e
*
fp12
)
double
(
c
,
a
*
fe12
)
{
fp6
:=
e
.
fp6
fp6
.
double
(
&
c
[
0
],
&
a
[
0
])
fp6
.
double
(
&
c
[
1
],
&
a
[
1
])
}
func
(
e
*
fp12
)
sub
(
c
,
a
,
b
*
fe12
)
{
fp6
:=
e
.
fp6
fp6
.
sub
(
&
c
[
0
],
&
a
[
0
],
&
b
[
0
])
fp6
.
sub
(
&
c
[
1
],
&
a
[
1
],
&
b
[
1
])
}
func
(
e
*
fp12
)
neg
(
c
,
a
*
fe12
)
{
fp6
:=
e
.
fp6
fp6
.
neg
(
&
c
[
0
],
&
a
[
0
])
fp6
.
neg
(
&
c
[
1
],
&
a
[
1
])
}
func
(
e
*
fp12
)
conjugate
(
c
,
a
*
fe12
)
{
fp6
:=
e
.
fp6
c
[
0
]
.
set
(
&
a
[
0
])
fp6
.
neg
(
&
c
[
1
],
&
a
[
1
])
}
func
(
e
*
fp12
)
square
(
c
,
a
*
fe12
)
{
fp6
,
t
:=
e
.
fp6
,
e
.
t6
fp6
.
add
(
t
[
0
],
&
a
[
0
],
&
a
[
1
])
fp6
.
mul
(
t
[
2
],
&
a
[
0
],
&
a
[
1
])
fp6
.
mulByNonResidue
(
t
[
1
],
&
a
[
1
])
fp6
.
addAssign
(
t
[
1
],
&
a
[
0
])
fp6
.
mulByNonResidue
(
t
[
3
],
t
[
2
])
fp6
.
mulAssign
(
t
[
0
],
t
[
1
])
fp6
.
subAssign
(
t
[
0
],
t
[
2
])
fp6
.
sub
(
&
c
[
0
],
t
[
0
],
t
[
3
])
fp6
.
double
(
&
c
[
1
],
t
[
2
])
}
func
(
e
*
fp12
)
cyclotomicSquare
(
c
,
a
*
fe12
)
{
t
,
fp2
:=
e
.
t2
,
e
.
fp2
()
e
.
fp4Square
(
t
[
3
],
t
[
4
],
&
a
[
0
][
0
],
&
a
[
1
][
1
])
fp2
.
sub
(
t
[
2
],
t
[
3
],
&
a
[
0
][
0
])
fp2
.
doubleAssign
(
t
[
2
])
fp2
.
add
(
&
c
[
0
][
0
],
t
[
2
],
t
[
3
])
fp2
.
add
(
t
[
2
],
t
[
4
],
&
a
[
1
][
1
])
fp2
.
doubleAssign
(
t
[
2
])
fp2
.
add
(
&
c
[
1
][
1
],
t
[
2
],
t
[
4
])
e
.
fp4Square
(
t
[
3
],
t
[
4
],
&
a
[
1
][
0
],
&
a
[
0
][
2
])
e
.
fp4Square
(
t
[
5
],
t
[
6
],
&
a
[
0
][
1
],
&
a
[
1
][
2
])
fp2
.
sub
(
t
[
2
],
t
[
3
],
&
a
[
0
][
1
])
fp2
.
doubleAssign
(
t
[
2
])
fp2
.
add
(
&
c
[
0
][
1
],
t
[
2
],
t
[
3
])
fp2
.
add
(
t
[
2
],
t
[
4
],
&
a
[
1
][
2
])
fp2
.
doubleAssign
(
t
[
2
])
fp2
.
add
(
&
c
[
1
][
2
],
t
[
2
],
t
[
4
])
fp2
.
mulByNonResidue
(
t
[
3
],
t
[
6
])
fp2
.
add
(
t
[
2
],
t
[
3
],
&
a
[
1
][
0
])
fp2
.
doubleAssign
(
t
[
2
])
fp2
.
add
(
&
c
[
1
][
0
],
t
[
2
],
t
[
3
])
fp2
.
sub
(
t
[
2
],
t
[
5
],
&
a
[
0
][
2
])
fp2
.
doubleAssign
(
t
[
2
])
fp2
.
add
(
&
c
[
0
][
2
],
t
[
2
],
t
[
5
])
}
func
(
e
*
fp12
)
mul
(
c
,
a
,
b
*
fe12
)
{
t
,
fp6
:=
e
.
t6
,
e
.
fp6
fp6
.
mul
(
t
[
1
],
&
a
[
0
],
&
b
[
0
])
fp6
.
mul
(
t
[
2
],
&
a
[
1
],
&
b
[
1
])
fp6
.
add
(
t
[
0
],
t
[
1
],
t
[
2
])
fp6
.
mulByNonResidue
(
t
[
2
],
t
[
2
])
fp6
.
add
(
t
[
3
],
t
[
1
],
t
[
2
])
fp6
.
add
(
t
[
1
],
&
a
[
0
],
&
a
[
1
])
fp6
.
add
(
t
[
2
],
&
b
[
0
],
&
b
[
1
])
fp6
.
mulAssign
(
t
[
1
],
t
[
2
])
c
[
0
]
.
set
(
t
[
3
])
fp6
.
sub
(
&
c
[
1
],
t
[
1
],
t
[
0
])
}
func
(
e
*
fp12
)
mulAssign
(
a
,
b
*
fe12
)
{
t
,
fp6
:=
e
.
t6
,
e
.
fp6
fp6
.
mul
(
t
[
1
],
&
a
[
0
],
&
b
[
0
])
fp6
.
mul
(
t
[
2
],
&
a
[
1
],
&
b
[
1
])
fp6
.
add
(
t
[
0
],
t
[
1
],
t
[
2
])
fp6
.
mulByNonResidue
(
t
[
2
],
t
[
2
])
fp6
.
add
(
t
[
3
],
t
[
1
],
t
[
2
])
fp6
.
add
(
t
[
1
],
&
a
[
0
],
&
a
[
1
])
fp6
.
add
(
t
[
2
],
&
b
[
0
],
&
b
[
1
])
fp6
.
mulAssign
(
t
[
1
],
t
[
2
])
a
[
0
]
.
set
(
t
[
3
])
fp6
.
sub
(
&
a
[
1
],
t
[
1
],
t
[
0
])
}
func
(
e
*
fp12
)
fp4Square
(
c0
,
c1
,
a0
,
a1
*
fe2
)
{
t
,
fp2
:=
e
.
t2
,
e
.
fp2
()
fp2
.
square
(
t
[
0
],
a0
)
fp2
.
square
(
t
[
1
],
a1
)
fp2
.
mulByNonResidue
(
t
[
2
],
t
[
1
])
fp2
.
add
(
c0
,
t
[
2
],
t
[
0
])
fp2
.
add
(
t
[
2
],
a0
,
a1
)
fp2
.
squareAssign
(
t
[
2
])
fp2
.
subAssign
(
t
[
2
],
t
[
0
])
fp2
.
sub
(
c1
,
t
[
2
],
t
[
1
])
}
func
(
e
*
fp12
)
inverse
(
c
,
a
*
fe12
)
{
fp6
,
t
:=
e
.
fp6
,
e
.
t6
fp6
.
square
(
t
[
0
],
&
a
[
0
])
fp6
.
square
(
t
[
1
],
&
a
[
1
])
fp6
.
mulByNonResidue
(
t
[
1
],
t
[
1
])
fp6
.
sub
(
t
[
1
],
t
[
0
],
t
[
1
])
fp6
.
inverse
(
t
[
0
],
t
[
1
])
fp6
.
mul
(
&
c
[
0
],
&
a
[
0
],
t
[
0
])
fp6
.
mulAssign
(
t
[
0
],
&
a
[
1
])
fp6
.
neg
(
&
c
[
1
],
t
[
0
])
}
func
(
e
*
fp12
)
mulBy014Assign
(
a
*
fe12
,
c0
,
c1
,
c4
*
fe2
)
{
fp2
,
fp6
,
t
,
t2
:=
e
.
fp2
(),
e
.
fp6
,
e
.
t6
,
e
.
t2
[
0
]
fp6
.
mulBy01
(
t
[
0
],
&
a
[
0
],
c0
,
c1
)
fp6
.
mulBy1
(
t
[
1
],
&
a
[
1
],
c4
)
fp2
.
add
(
t2
,
c1
,
c4
)
fp6
.
add
(
t
[
2
],
&
a
[
1
],
&
a
[
0
])
fp6
.
mulBy01Assign
(
t
[
2
],
c0
,
t2
)
fp6
.
subAssign
(
t
[
2
],
t
[
0
])
fp6
.
sub
(
&
a
[
1
],
t
[
2
],
t
[
1
])
fp6
.
mulByNonResidue
(
t
[
1
],
t
[
1
])
fp6
.
add
(
&
a
[
0
],
t
[
1
],
t
[
0
])
}
func
(
e
*
fp12
)
exp
(
c
,
a
*
fe12
,
s
*
big
.
Int
)
{
z
:=
e
.
one
()
for
i
:=
s
.
BitLen
()
-
1
;
i
>=
0
;
i
--
{
e
.
square
(
z
,
z
)
if
s
.
Bit
(
i
)
==
1
{
e
.
mul
(
z
,
z
,
a
)
}
}
c
.
set
(
z
)
}
func
(
e
*
fp12
)
cyclotomicExp
(
c
,
a
*
fe12
,
s
*
big
.
Int
)
{
z
:=
e
.
one
()
for
i
:=
s
.
BitLen
()
-
1
;
i
>=
0
;
i
--
{
e
.
cyclotomicSquare
(
z
,
z
)
if
s
.
Bit
(
i
)
==
1
{
e
.
mul
(
z
,
z
,
a
)
}
}
c
.
set
(
z
)
}
func
(
e
*
fp12
)
frobeniusMap
(
c
,
a
*
fe12
,
power
uint
)
{
fp6
:=
e
.
fp6
fp6
.
frobeniusMap
(
&
c
[
0
],
&
a
[
0
],
power
)
fp6
.
frobeniusMap
(
&
c
[
1
],
&
a
[
1
],
power
)
switch
power
{
case
0
:
return
case
6
:
fp6
.
neg
(
&
c
[
1
],
&
c
[
1
])
default
:
fp6
.
mulByBaseField
(
&
c
[
1
],
&
c
[
1
],
&
frobeniusCoeffs12
[
power
])
}
}
func
(
e
*
fp12
)
frobeniusMapAssign
(
a
*
fe12
,
power
uint
)
{
fp6
:=
e
.
fp6
fp6
.
frobeniusMapAssign
(
&
a
[
0
],
power
)
fp6
.
frobeniusMapAssign
(
&
a
[
1
],
power
)
switch
power
{
case
0
:
return
case
6
:
fp6
.
neg
(
&
a
[
1
],
&
a
[
1
])
default
:
fp6
.
mulByBaseField
(
&
a
[
1
],
&
a
[
1
],
&
frobeniusCoeffs12
[
power
])
}
}
minigeth/crypto/bls12381/fp2.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"errors"
"math/big"
)
type
fp2Temp
struct
{
t
[
4
]
*
fe
}
type
fp2
struct
{
fp2Temp
}
func
newFp2Temp
()
fp2Temp
{
t
:=
[
4
]
*
fe
{}
for
i
:=
0
;
i
<
len
(
t
);
i
++
{
t
[
i
]
=
&
fe
{}
}
return
fp2Temp
{
t
}
}
func
newFp2
()
*
fp2
{
t
:=
newFp2Temp
()
return
&
fp2
{
t
}
}
func
(
e
*
fp2
)
fromBytes
(
in
[]
byte
)
(
*
fe2
,
error
)
{
if
len
(
in
)
!=
96
{
return
nil
,
errors
.
New
(
"length of input string should be 96 bytes"
)
}
c1
,
err
:=
fromBytes
(
in
[
:
48
])
if
err
!=
nil
{
return
nil
,
err
}
c0
,
err
:=
fromBytes
(
in
[
48
:
])
if
err
!=
nil
{
return
nil
,
err
}
return
&
fe2
{
*
c0
,
*
c1
},
nil
}
func
(
e
*
fp2
)
toBytes
(
a
*
fe2
)
[]
byte
{
out
:=
make
([]
byte
,
96
)
copy
(
out
[
:
48
],
toBytes
(
&
a
[
1
]))
copy
(
out
[
48
:
],
toBytes
(
&
a
[
0
]))
return
out
}
func
(
e
*
fp2
)
new
()
*
fe2
{
return
new
(
fe2
)
.
zero
()
}
func
(
e
*
fp2
)
zero
()
*
fe2
{
return
new
(
fe2
)
.
zero
()
}
func
(
e
*
fp2
)
one
()
*
fe2
{
return
new
(
fe2
)
.
one
()
}
func
(
e
*
fp2
)
add
(
c
,
a
,
b
*
fe2
)
{
add
(
&
c
[
0
],
&
a
[
0
],
&
b
[
0
])
add
(
&
c
[
1
],
&
a
[
1
],
&
b
[
1
])
}
func
(
e
*
fp2
)
addAssign
(
a
,
b
*
fe2
)
{
addAssign
(
&
a
[
0
],
&
b
[
0
])
addAssign
(
&
a
[
1
],
&
b
[
1
])
}
func
(
e
*
fp2
)
ladd
(
c
,
a
,
b
*
fe2
)
{
ladd
(
&
c
[
0
],
&
a
[
0
],
&
b
[
0
])
ladd
(
&
c
[
1
],
&
a
[
1
],
&
b
[
1
])
}
func
(
e
*
fp2
)
double
(
c
,
a
*
fe2
)
{
double
(
&
c
[
0
],
&
a
[
0
])
double
(
&
c
[
1
],
&
a
[
1
])
}
func
(
e
*
fp2
)
doubleAssign
(
a
*
fe2
)
{
doubleAssign
(
&
a
[
0
])
doubleAssign
(
&
a
[
1
])
}
func
(
e
*
fp2
)
ldouble
(
c
,
a
*
fe2
)
{
ldouble
(
&
c
[
0
],
&
a
[
0
])
ldouble
(
&
c
[
1
],
&
a
[
1
])
}
func
(
e
*
fp2
)
sub
(
c
,
a
,
b
*
fe2
)
{
sub
(
&
c
[
0
],
&
a
[
0
],
&
b
[
0
])
sub
(
&
c
[
1
],
&
a
[
1
],
&
b
[
1
])
}
func
(
e
*
fp2
)
subAssign
(
c
,
a
*
fe2
)
{
subAssign
(
&
c
[
0
],
&
a
[
0
])
subAssign
(
&
c
[
1
],
&
a
[
1
])
}
func
(
e
*
fp2
)
neg
(
c
,
a
*
fe2
)
{
neg
(
&
c
[
0
],
&
a
[
0
])
neg
(
&
c
[
1
],
&
a
[
1
])
}
func
(
e
*
fp2
)
mul
(
c
,
a
,
b
*
fe2
)
{
t
:=
e
.
t
mul
(
t
[
1
],
&
a
[
0
],
&
b
[
0
])
mul
(
t
[
2
],
&
a
[
1
],
&
b
[
1
])
add
(
t
[
0
],
&
a
[
0
],
&
a
[
1
])
add
(
t
[
3
],
&
b
[
0
],
&
b
[
1
])
sub
(
&
c
[
0
],
t
[
1
],
t
[
2
])
addAssign
(
t
[
1
],
t
[
2
])
mul
(
t
[
0
],
t
[
0
],
t
[
3
])
sub
(
&
c
[
1
],
t
[
0
],
t
[
1
])
}
func
(
e
*
fp2
)
mulAssign
(
a
,
b
*
fe2
)
{
t
:=
e
.
t
mul
(
t
[
1
],
&
a
[
0
],
&
b
[
0
])
mul
(
t
[
2
],
&
a
[
1
],
&
b
[
1
])
add
(
t
[
0
],
&
a
[
0
],
&
a
[
1
])
add
(
t
[
3
],
&
b
[
0
],
&
b
[
1
])
sub
(
&
a
[
0
],
t
[
1
],
t
[
2
])
addAssign
(
t
[
1
],
t
[
2
])
mul
(
t
[
0
],
t
[
0
],
t
[
3
])
sub
(
&
a
[
1
],
t
[
0
],
t
[
1
])
}
func
(
e
*
fp2
)
square
(
c
,
a
*
fe2
)
{
t
:=
e
.
t
ladd
(
t
[
0
],
&
a
[
0
],
&
a
[
1
])
sub
(
t
[
1
],
&
a
[
0
],
&
a
[
1
])
ldouble
(
t
[
2
],
&
a
[
0
])
mul
(
&
c
[
0
],
t
[
0
],
t
[
1
])
mul
(
&
c
[
1
],
t
[
2
],
&
a
[
1
])
}
func
(
e
*
fp2
)
squareAssign
(
a
*
fe2
)
{
t
:=
e
.
t
ladd
(
t
[
0
],
&
a
[
0
],
&
a
[
1
])
sub
(
t
[
1
],
&
a
[
0
],
&
a
[
1
])
ldouble
(
t
[
2
],
&
a
[
0
])
mul
(
&
a
[
0
],
t
[
0
],
t
[
1
])
mul
(
&
a
[
1
],
t
[
2
],
&
a
[
1
])
}
func
(
e
*
fp2
)
mulByNonResidue
(
c
,
a
*
fe2
)
{
t
:=
e
.
t
sub
(
t
[
0
],
&
a
[
0
],
&
a
[
1
])
add
(
&
c
[
1
],
&
a
[
0
],
&
a
[
1
])
c
[
0
]
.
set
(
t
[
0
])
}
func
(
e
*
fp2
)
mulByB
(
c
,
a
*
fe2
)
{
t
:=
e
.
t
double
(
t
[
0
],
&
a
[
0
])
double
(
t
[
1
],
&
a
[
1
])
doubleAssign
(
t
[
0
])
doubleAssign
(
t
[
1
])
sub
(
&
c
[
0
],
t
[
0
],
t
[
1
])
add
(
&
c
[
1
],
t
[
0
],
t
[
1
])
}
func
(
e
*
fp2
)
inverse
(
c
,
a
*
fe2
)
{
t
:=
e
.
t
square
(
t
[
0
],
&
a
[
0
])
square
(
t
[
1
],
&
a
[
1
])
addAssign
(
t
[
0
],
t
[
1
])
inverse
(
t
[
0
],
t
[
0
])
mul
(
&
c
[
0
],
&
a
[
0
],
t
[
0
])
mul
(
t
[
0
],
t
[
0
],
&
a
[
1
])
neg
(
&
c
[
1
],
t
[
0
])
}
func
(
e
*
fp2
)
mulByFq
(
c
,
a
*
fe2
,
b
*
fe
)
{
mul
(
&
c
[
0
],
&
a
[
0
],
b
)
mul
(
&
c
[
1
],
&
a
[
1
],
b
)
}
func
(
e
*
fp2
)
exp
(
c
,
a
*
fe2
,
s
*
big
.
Int
)
{
z
:=
e
.
one
()
for
i
:=
s
.
BitLen
()
-
1
;
i
>=
0
;
i
--
{
e
.
square
(
z
,
z
)
if
s
.
Bit
(
i
)
==
1
{
e
.
mul
(
z
,
z
,
a
)
}
}
c
.
set
(
z
)
}
func
(
e
*
fp2
)
frobeniusMap
(
c
,
a
*
fe2
,
power
uint
)
{
c
[
0
]
.
set
(
&
a
[
0
])
if
power
%
2
==
1
{
neg
(
&
c
[
1
],
&
a
[
1
])
return
}
c
[
1
]
.
set
(
&
a
[
1
])
}
func
(
e
*
fp2
)
frobeniusMapAssign
(
a
*
fe2
,
power
uint
)
{
if
power
%
2
==
1
{
neg
(
&
a
[
1
],
&
a
[
1
])
return
}
}
func
(
e
*
fp2
)
sqrt
(
c
,
a
*
fe2
)
bool
{
u
,
x0
,
a1
,
alpha
:=
&
fe2
{},
&
fe2
{},
&
fe2
{},
&
fe2
{}
u
.
set
(
a
)
e
.
exp
(
a1
,
a
,
pMinus3Over4
)
e
.
square
(
alpha
,
a1
)
e
.
mul
(
alpha
,
alpha
,
a
)
e
.
mul
(
x0
,
a1
,
a
)
if
alpha
.
equal
(
negativeOne2
)
{
neg
(
&
c
[
0
],
&
x0
[
1
])
c
[
1
]
.
set
(
&
x0
[
0
])
return
true
}
e
.
add
(
alpha
,
alpha
,
e
.
one
())
e
.
exp
(
alpha
,
alpha
,
pMinus1Over2
)
e
.
mul
(
c
,
alpha
,
x0
)
e
.
square
(
alpha
,
c
)
return
alpha
.
equal
(
u
)
}
func
(
e
*
fp2
)
isQuadraticNonResidue
(
a
*
fe2
)
bool
{
// https://github.com/leovt/constructible/wiki/Taking-Square-Roots-in-quadratic-extension-Fields
c0
,
c1
:=
new
(
fe
),
new
(
fe
)
square
(
c0
,
&
a
[
0
])
square
(
c1
,
&
a
[
1
])
add
(
c1
,
c1
,
c0
)
return
isQuadraticNonResidue
(
c1
)
}
minigeth/crypto/bls12381/fp6.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"errors"
"math/big"
)
type
fp6Temp
struct
{
t
[
6
]
*
fe2
}
type
fp6
struct
{
fp2
*
fp2
fp6Temp
}
func
newFp6Temp
()
fp6Temp
{
t
:=
[
6
]
*
fe2
{}
for
i
:=
0
;
i
<
len
(
t
);
i
++
{
t
[
i
]
=
&
fe2
{}
}
return
fp6Temp
{
t
}
}
func
newFp6
(
f
*
fp2
)
*
fp6
{
t
:=
newFp6Temp
()
if
f
==
nil
{
return
&
fp6
{
newFp2
(),
t
}
}
return
&
fp6
{
f
,
t
}
}
func
(
e
*
fp6
)
fromBytes
(
b
[]
byte
)
(
*
fe6
,
error
)
{
if
len
(
b
)
<
288
{
return
nil
,
errors
.
New
(
"input string should be larger than 288 bytes"
)
}
fp2
:=
e
.
fp2
u2
,
err
:=
fp2
.
fromBytes
(
b
[
:
96
])
if
err
!=
nil
{
return
nil
,
err
}
u1
,
err
:=
fp2
.
fromBytes
(
b
[
96
:
192
])
if
err
!=
nil
{
return
nil
,
err
}
u0
,
err
:=
fp2
.
fromBytes
(
b
[
192
:
])
if
err
!=
nil
{
return
nil
,
err
}
return
&
fe6
{
*
u0
,
*
u1
,
*
u2
},
nil
}
func
(
e
*
fp6
)
toBytes
(
a
*
fe6
)
[]
byte
{
fp2
:=
e
.
fp2
out
:=
make
([]
byte
,
288
)
copy
(
out
[
:
96
],
fp2
.
toBytes
(
&
a
[
2
]))
copy
(
out
[
96
:
192
],
fp2
.
toBytes
(
&
a
[
1
]))
copy
(
out
[
192
:
],
fp2
.
toBytes
(
&
a
[
0
]))
return
out
}
func
(
e
*
fp6
)
new
()
*
fe6
{
return
new
(
fe6
)
}
func
(
e
*
fp6
)
zero
()
*
fe6
{
return
new
(
fe6
)
}
func
(
e
*
fp6
)
one
()
*
fe6
{
return
new
(
fe6
)
.
one
()
}
func
(
e
*
fp6
)
add
(
c
,
a
,
b
*
fe6
)
{
fp2
:=
e
.
fp2
fp2
.
add
(
&
c
[
0
],
&
a
[
0
],
&
b
[
0
])
fp2
.
add
(
&
c
[
1
],
&
a
[
1
],
&
b
[
1
])
fp2
.
add
(
&
c
[
2
],
&
a
[
2
],
&
b
[
2
])
}
func
(
e
*
fp6
)
addAssign
(
a
,
b
*
fe6
)
{
fp2
:=
e
.
fp2
fp2
.
addAssign
(
&
a
[
0
],
&
b
[
0
])
fp2
.
addAssign
(
&
a
[
1
],
&
b
[
1
])
fp2
.
addAssign
(
&
a
[
2
],
&
b
[
2
])
}
func
(
e
*
fp6
)
double
(
c
,
a
*
fe6
)
{
fp2
:=
e
.
fp2
fp2
.
double
(
&
c
[
0
],
&
a
[
0
])
fp2
.
double
(
&
c
[
1
],
&
a
[
1
])
fp2
.
double
(
&
c
[
2
],
&
a
[
2
])
}
func
(
e
*
fp6
)
doubleAssign
(
a
*
fe6
)
{
fp2
:=
e
.
fp2
fp2
.
doubleAssign
(
&
a
[
0
])
fp2
.
doubleAssign
(
&
a
[
1
])
fp2
.
doubleAssign
(
&
a
[
2
])
}
func
(
e
*
fp6
)
sub
(
c
,
a
,
b
*
fe6
)
{
fp2
:=
e
.
fp2
fp2
.
sub
(
&
c
[
0
],
&
a
[
0
],
&
b
[
0
])
fp2
.
sub
(
&
c
[
1
],
&
a
[
1
],
&
b
[
1
])
fp2
.
sub
(
&
c
[
2
],
&
a
[
2
],
&
b
[
2
])
}
func
(
e
*
fp6
)
subAssign
(
a
,
b
*
fe6
)
{
fp2
:=
e
.
fp2
fp2
.
subAssign
(
&
a
[
0
],
&
b
[
0
])
fp2
.
subAssign
(
&
a
[
1
],
&
b
[
1
])
fp2
.
subAssign
(
&
a
[
2
],
&
b
[
2
])
}
func
(
e
*
fp6
)
neg
(
c
,
a
*
fe6
)
{
fp2
:=
e
.
fp2
fp2
.
neg
(
&
c
[
0
],
&
a
[
0
])
fp2
.
neg
(
&
c
[
1
],
&
a
[
1
])
fp2
.
neg
(
&
c
[
2
],
&
a
[
2
])
}
func
(
e
*
fp6
)
mul
(
c
,
a
,
b
*
fe6
)
{
fp2
,
t
:=
e
.
fp2
,
e
.
t
fp2
.
mul
(
t
[
0
],
&
a
[
0
],
&
b
[
0
])
fp2
.
mul
(
t
[
1
],
&
a
[
1
],
&
b
[
1
])
fp2
.
mul
(
t
[
2
],
&
a
[
2
],
&
b
[
2
])
fp2
.
add
(
t
[
3
],
&
a
[
1
],
&
a
[
2
])
fp2
.
add
(
t
[
4
],
&
b
[
1
],
&
b
[
2
])
fp2
.
mulAssign
(
t
[
3
],
t
[
4
])
fp2
.
add
(
t
[
4
],
t
[
1
],
t
[
2
])
fp2
.
subAssign
(
t
[
3
],
t
[
4
])
fp2
.
mulByNonResidue
(
t
[
3
],
t
[
3
])
fp2
.
add
(
t
[
5
],
t
[
0
],
t
[
3
])
fp2
.
add
(
t
[
3
],
&
a
[
0
],
&
a
[
1
])
fp2
.
add
(
t
[
4
],
&
b
[
0
],
&
b
[
1
])
fp2
.
mulAssign
(
t
[
3
],
t
[
4
])
fp2
.
add
(
t
[
4
],
t
[
0
],
t
[
1
])
fp2
.
subAssign
(
t
[
3
],
t
[
4
])
fp2
.
mulByNonResidue
(
t
[
4
],
t
[
2
])
fp2
.
add
(
&
c
[
1
],
t
[
3
],
t
[
4
])
fp2
.
add
(
t
[
3
],
&
a
[
0
],
&
a
[
2
])
fp2
.
add
(
t
[
4
],
&
b
[
0
],
&
b
[
2
])
fp2
.
mulAssign
(
t
[
3
],
t
[
4
])
fp2
.
add
(
t
[
4
],
t
[
0
],
t
[
2
])
fp2
.
subAssign
(
t
[
3
],
t
[
4
])
fp2
.
add
(
&
c
[
2
],
t
[
1
],
t
[
3
])
c
[
0
]
.
set
(
t
[
5
])
}
func
(
e
*
fp6
)
mulAssign
(
a
,
b
*
fe6
)
{
fp2
,
t
:=
e
.
fp2
,
e
.
t
fp2
.
mul
(
t
[
0
],
&
a
[
0
],
&
b
[
0
])
fp2
.
mul
(
t
[
1
],
&
a
[
1
],
&
b
[
1
])
fp2
.
mul
(
t
[
2
],
&
a
[
2
],
&
b
[
2
])
fp2
.
add
(
t
[
3
],
&
a
[
1
],
&
a
[
2
])
fp2
.
add
(
t
[
4
],
&
b
[
1
],
&
b
[
2
])
fp2
.
mulAssign
(
t
[
3
],
t
[
4
])
fp2
.
add
(
t
[
4
],
t
[
1
],
t
[
2
])
fp2
.
subAssign
(
t
[
3
],
t
[
4
])
fp2
.
mulByNonResidue
(
t
[
3
],
t
[
3
])
fp2
.
add
(
t
[
5
],
t
[
0
],
t
[
3
])
fp2
.
add
(
t
[
3
],
&
a
[
0
],
&
a
[
1
])
fp2
.
add
(
t
[
4
],
&
b
[
0
],
&
b
[
1
])
fp2
.
mulAssign
(
t
[
3
],
t
[
4
])
fp2
.
add
(
t
[
4
],
t
[
0
],
t
[
1
])
fp2
.
subAssign
(
t
[
3
],
t
[
4
])
fp2
.
mulByNonResidue
(
t
[
4
],
t
[
2
])
fp2
.
add
(
&
a
[
1
],
t
[
3
],
t
[
4
])
fp2
.
add
(
t
[
3
],
&
a
[
0
],
&
a
[
2
])
fp2
.
add
(
t
[
4
],
&
b
[
0
],
&
b
[
2
])
fp2
.
mulAssign
(
t
[
3
],
t
[
4
])
fp2
.
add
(
t
[
4
],
t
[
0
],
t
[
2
])
fp2
.
subAssign
(
t
[
3
],
t
[
4
])
fp2
.
add
(
&
a
[
2
],
t
[
1
],
t
[
3
])
a
[
0
]
.
set
(
t
[
5
])
}
func
(
e
*
fp6
)
square
(
c
,
a
*
fe6
)
{
fp2
,
t
:=
e
.
fp2
,
e
.
t
fp2
.
square
(
t
[
0
],
&
a
[
0
])
fp2
.
mul
(
t
[
1
],
&
a
[
0
],
&
a
[
1
])
fp2
.
doubleAssign
(
t
[
1
])
fp2
.
sub
(
t
[
2
],
&
a
[
0
],
&
a
[
1
])
fp2
.
addAssign
(
t
[
2
],
&
a
[
2
])
fp2
.
squareAssign
(
t
[
2
])
fp2
.
mul
(
t
[
3
],
&
a
[
1
],
&
a
[
2
])
fp2
.
doubleAssign
(
t
[
3
])
fp2
.
square
(
t
[
4
],
&
a
[
2
])
fp2
.
mulByNonResidue
(
t
[
5
],
t
[
3
])
fp2
.
add
(
&
c
[
0
],
t
[
0
],
t
[
5
])
fp2
.
mulByNonResidue
(
t
[
5
],
t
[
4
])
fp2
.
add
(
&
c
[
1
],
t
[
1
],
t
[
5
])
fp2
.
addAssign
(
t
[
1
],
t
[
2
])
fp2
.
addAssign
(
t
[
1
],
t
[
3
])
fp2
.
addAssign
(
t
[
0
],
t
[
4
])
fp2
.
sub
(
&
c
[
2
],
t
[
1
],
t
[
0
])
}
func
(
e
*
fp6
)
mulBy01Assign
(
a
*
fe6
,
b0
,
b1
*
fe2
)
{
fp2
,
t
:=
e
.
fp2
,
e
.
t
fp2
.
mul
(
t
[
0
],
&
a
[
0
],
b0
)
fp2
.
mul
(
t
[
1
],
&
a
[
1
],
b1
)
fp2
.
add
(
t
[
5
],
&
a
[
1
],
&
a
[
2
])
fp2
.
mul
(
t
[
2
],
b1
,
t
[
5
])
fp2
.
subAssign
(
t
[
2
],
t
[
1
])
fp2
.
mulByNonResidue
(
t
[
2
],
t
[
2
])
fp2
.
add
(
t
[
5
],
&
a
[
0
],
&
a
[
2
])
fp2
.
mul
(
t
[
3
],
b0
,
t
[
5
])
fp2
.
subAssign
(
t
[
3
],
t
[
0
])
fp2
.
add
(
&
a
[
2
],
t
[
3
],
t
[
1
])
fp2
.
add
(
t
[
4
],
b0
,
b1
)
fp2
.
add
(
t
[
5
],
&
a
[
0
],
&
a
[
1
])
fp2
.
mulAssign
(
t
[
4
],
t
[
5
])
fp2
.
subAssign
(
t
[
4
],
t
[
0
])
fp2
.
sub
(
&
a
[
1
],
t
[
4
],
t
[
1
])
fp2
.
add
(
&
a
[
0
],
t
[
2
],
t
[
0
])
}
func
(
e
*
fp6
)
mulBy01
(
c
,
a
*
fe6
,
b0
,
b1
*
fe2
)
{
fp2
,
t
:=
e
.
fp2
,
e
.
t
fp2
.
mul
(
t
[
0
],
&
a
[
0
],
b0
)
fp2
.
mul
(
t
[
1
],
&
a
[
1
],
b1
)
fp2
.
add
(
t
[
2
],
&
a
[
1
],
&
a
[
2
])
fp2
.
mulAssign
(
t
[
2
],
b1
)
fp2
.
subAssign
(
t
[
2
],
t
[
1
])
fp2
.
mulByNonResidue
(
t
[
2
],
t
[
2
])
fp2
.
add
(
t
[
3
],
&
a
[
0
],
&
a
[
2
])
fp2
.
mulAssign
(
t
[
3
],
b0
)
fp2
.
subAssign
(
t
[
3
],
t
[
0
])
fp2
.
add
(
&
c
[
2
],
t
[
3
],
t
[
1
])
fp2
.
add
(
t
[
4
],
b0
,
b1
)
fp2
.
add
(
t
[
3
],
&
a
[
0
],
&
a
[
1
])
fp2
.
mulAssign
(
t
[
4
],
t
[
3
])
fp2
.
subAssign
(
t
[
4
],
t
[
0
])
fp2
.
sub
(
&
c
[
1
],
t
[
4
],
t
[
1
])
fp2
.
add
(
&
c
[
0
],
t
[
2
],
t
[
0
])
}
func
(
e
*
fp6
)
mulBy1
(
c
,
a
*
fe6
,
b1
*
fe2
)
{
fp2
,
t
:=
e
.
fp2
,
e
.
t
fp2
.
mul
(
t
[
0
],
&
a
[
2
],
b1
)
fp2
.
mul
(
&
c
[
2
],
&
a
[
1
],
b1
)
fp2
.
mul
(
&
c
[
1
],
&
a
[
0
],
b1
)
fp2
.
mulByNonResidue
(
&
c
[
0
],
t
[
0
])
}
func
(
e
*
fp6
)
mulByNonResidue
(
c
,
a
*
fe6
)
{
fp2
,
t
:=
e
.
fp2
,
e
.
t
t
[
0
]
.
set
(
&
a
[
0
])
fp2
.
mulByNonResidue
(
&
c
[
0
],
&
a
[
2
])
c
[
2
]
.
set
(
&
a
[
1
])
c
[
1
]
.
set
(
t
[
0
])
}
func
(
e
*
fp6
)
mulByBaseField
(
c
,
a
*
fe6
,
b
*
fe2
)
{
fp2
:=
e
.
fp2
fp2
.
mul
(
&
c
[
0
],
&
a
[
0
],
b
)
fp2
.
mul
(
&
c
[
1
],
&
a
[
1
],
b
)
fp2
.
mul
(
&
c
[
2
],
&
a
[
2
],
b
)
}
func
(
e
*
fp6
)
exp
(
c
,
a
*
fe6
,
s
*
big
.
Int
)
{
z
:=
e
.
one
()
for
i
:=
s
.
BitLen
()
-
1
;
i
>=
0
;
i
--
{
e
.
square
(
z
,
z
)
if
s
.
Bit
(
i
)
==
1
{
e
.
mul
(
z
,
z
,
a
)
}
}
c
.
set
(
z
)
}
func
(
e
*
fp6
)
inverse
(
c
,
a
*
fe6
)
{
fp2
,
t
:=
e
.
fp2
,
e
.
t
fp2
.
square
(
t
[
0
],
&
a
[
0
])
fp2
.
mul
(
t
[
1
],
&
a
[
1
],
&
a
[
2
])
fp2
.
mulByNonResidue
(
t
[
1
],
t
[
1
])
fp2
.
subAssign
(
t
[
0
],
t
[
1
])
fp2
.
square
(
t
[
1
],
&
a
[
1
])
fp2
.
mul
(
t
[
2
],
&
a
[
0
],
&
a
[
2
])
fp2
.
subAssign
(
t
[
1
],
t
[
2
])
fp2
.
square
(
t
[
2
],
&
a
[
2
])
fp2
.
mulByNonResidue
(
t
[
2
],
t
[
2
])
fp2
.
mul
(
t
[
3
],
&
a
[
0
],
&
a
[
1
])
fp2
.
subAssign
(
t
[
2
],
t
[
3
])
fp2
.
mul
(
t
[
3
],
&
a
[
2
],
t
[
2
])
fp2
.
mul
(
t
[
4
],
&
a
[
1
],
t
[
1
])
fp2
.
addAssign
(
t
[
3
],
t
[
4
])
fp2
.
mulByNonResidue
(
t
[
3
],
t
[
3
])
fp2
.
mul
(
t
[
4
],
&
a
[
0
],
t
[
0
])
fp2
.
addAssign
(
t
[
3
],
t
[
4
])
fp2
.
inverse
(
t
[
3
],
t
[
3
])
fp2
.
mul
(
&
c
[
0
],
t
[
0
],
t
[
3
])
fp2
.
mul
(
&
c
[
1
],
t
[
2
],
t
[
3
])
fp2
.
mul
(
&
c
[
2
],
t
[
1
],
t
[
3
])
}
func
(
e
*
fp6
)
frobeniusMap
(
c
,
a
*
fe6
,
power
uint
)
{
fp2
:=
e
.
fp2
fp2
.
frobeniusMap
(
&
c
[
0
],
&
a
[
0
],
power
)
fp2
.
frobeniusMap
(
&
c
[
1
],
&
a
[
1
],
power
)
fp2
.
frobeniusMap
(
&
c
[
2
],
&
a
[
2
],
power
)
switch
power
%
6
{
case
0
:
return
case
3
:
neg
(
&
c
[
0
][
0
],
&
a
[
1
][
1
])
c
[
1
][
1
]
.
set
(
&
a
[
1
][
0
])
fp2
.
neg
(
&
a
[
2
],
&
a
[
2
])
default
:
fp2
.
mul
(
&
c
[
1
],
&
c
[
1
],
&
frobeniusCoeffs61
[
power
%
6
])
fp2
.
mul
(
&
c
[
2
],
&
c
[
2
],
&
frobeniusCoeffs62
[
power
%
6
])
}
}
func
(
e
*
fp6
)
frobeniusMapAssign
(
a
*
fe6
,
power
uint
)
{
fp2
:=
e
.
fp2
fp2
.
frobeniusMapAssign
(
&
a
[
0
],
power
)
fp2
.
frobeniusMapAssign
(
&
a
[
1
],
power
)
fp2
.
frobeniusMapAssign
(
&
a
[
2
],
power
)
t
:=
e
.
t
switch
power
%
6
{
case
0
:
return
case
3
:
neg
(
&
t
[
0
][
0
],
&
a
[
1
][
1
])
a
[
1
][
1
]
.
set
(
&
a
[
1
][
0
])
a
[
1
][
0
]
.
set
(
&
t
[
0
][
0
])
fp2
.
neg
(
&
a
[
2
],
&
a
[
2
])
default
:
fp2
.
mulAssign
(
&
a
[
1
],
&
frobeniusCoeffs61
[
power
%
6
])
fp2
.
mulAssign
(
&
a
[
2
],
&
frobeniusCoeffs62
[
power
%
6
])
}
}
minigeth/crypto/bls12381/g1.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"errors"
"math"
"math/big"
)
// PointG1 is type for point in G1.
// PointG1 is both used for Affine and Jacobian point representation.
// If z is equal to one the point is considered as in affine form.
type
PointG1
[
3
]
fe
func
(
p
*
PointG1
)
Set
(
p2
*
PointG1
)
*
PointG1
{
p
[
0
]
.
set
(
&
p2
[
0
])
p
[
1
]
.
set
(
&
p2
[
1
])
p
[
2
]
.
set
(
&
p2
[
2
])
return
p
}
// Zero returns G1 point in point at infinity representation
func
(
p
*
PointG1
)
Zero
()
*
PointG1
{
p
[
0
]
.
zero
()
p
[
1
]
.
one
()
p
[
2
]
.
zero
()
return
p
}
type
tempG1
struct
{
t
[
9
]
*
fe
}
// G1 is struct for G1 group.
type
G1
struct
{
tempG1
}
// NewG1 constructs a new G1 instance.
func
NewG1
()
*
G1
{
t
:=
newTempG1
()
return
&
G1
{
t
}
}
func
newTempG1
()
tempG1
{
t
:=
[
9
]
*
fe
{}
for
i
:=
0
;
i
<
9
;
i
++
{
t
[
i
]
=
&
fe
{}
}
return
tempG1
{
t
}
}
// Q returns group order in big.Int.
func
(
g
*
G1
)
Q
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
q
)
}
func
(
g
*
G1
)
fromBytesUnchecked
(
in
[]
byte
)
(
*
PointG1
,
error
)
{
p0
,
err
:=
fromBytes
(
in
[
:
48
])
if
err
!=
nil
{
return
nil
,
err
}
p1
,
err
:=
fromBytes
(
in
[
48
:
])
if
err
!=
nil
{
return
nil
,
err
}
p2
:=
new
(
fe
)
.
one
()
return
&
PointG1
{
*
p0
,
*
p1
,
*
p2
},
nil
}
// FromBytes constructs a new point given uncompressed byte input.
// FromBytes does not take zcash flags into account.
// Byte input expected to be larger than 96 bytes.
// First 96 bytes should be concatenation of x and y values.
// Point (0, 0) is considered as infinity.
func
(
g
*
G1
)
FromBytes
(
in
[]
byte
)
(
*
PointG1
,
error
)
{
if
len
(
in
)
!=
96
{
return
nil
,
errors
.
New
(
"input string should be equal or larger than 96"
)
}
p0
,
err
:=
fromBytes
(
in
[
:
48
])
if
err
!=
nil
{
return
nil
,
err
}
p1
,
err
:=
fromBytes
(
in
[
48
:
])
if
err
!=
nil
{
return
nil
,
err
}
// check if given input points to infinity
if
p0
.
isZero
()
&&
p1
.
isZero
()
{
return
g
.
Zero
(),
nil
}
p2
:=
new
(
fe
)
.
one
()
p
:=
&
PointG1
{
*
p0
,
*
p1
,
*
p2
}
if
!
g
.
IsOnCurve
(
p
)
{
return
nil
,
errors
.
New
(
"point is not on curve"
)
}
return
p
,
nil
}
// DecodePoint given encoded (x, y) coordinates in 128 bytes returns a valid G1 Point.
func
(
g
*
G1
)
DecodePoint
(
in
[]
byte
)
(
*
PointG1
,
error
)
{
if
len
(
in
)
!=
128
{
return
nil
,
errors
.
New
(
"invalid g1 point length"
)
}
pointBytes
:=
make
([]
byte
,
96
)
// decode x
xBytes
,
err
:=
decodeFieldElement
(
in
[
:
64
])
if
err
!=
nil
{
return
nil
,
err
}
// decode y
yBytes
,
err
:=
decodeFieldElement
(
in
[
64
:
])
if
err
!=
nil
{
return
nil
,
err
}
copy
(
pointBytes
[
:
48
],
xBytes
)
copy
(
pointBytes
[
48
:
],
yBytes
)
return
g
.
FromBytes
(
pointBytes
)
}
// ToBytes serializes a point into bytes in uncompressed form.
// ToBytes does not take zcash flags into account.
// ToBytes returns (0, 0) if point is infinity.
func
(
g
*
G1
)
ToBytes
(
p
*
PointG1
)
[]
byte
{
out
:=
make
([]
byte
,
96
)
if
g
.
IsZero
(
p
)
{
return
out
}
g
.
Affine
(
p
)
copy
(
out
[
:
48
],
toBytes
(
&
p
[
0
]))
copy
(
out
[
48
:
],
toBytes
(
&
p
[
1
]))
return
out
}
// EncodePoint encodes a point into 128 bytes.
func
(
g
*
G1
)
EncodePoint
(
p
*
PointG1
)
[]
byte
{
outRaw
:=
g
.
ToBytes
(
p
)
out
:=
make
([]
byte
,
128
)
// encode x
copy
(
out
[
16
:
],
outRaw
[
:
48
])
// encode y
copy
(
out
[
64
+
16
:
],
outRaw
[
48
:
])
return
out
}
// New creates a new G1 Point which is equal to zero in other words point at infinity.
func
(
g
*
G1
)
New
()
*
PointG1
{
return
g
.
Zero
()
}
// Zero returns a new G1 Point which is equal to point at infinity.
func
(
g
*
G1
)
Zero
()
*
PointG1
{
return
new
(
PointG1
)
.
Zero
()
}
// One returns a new G1 Point which is equal to generator point.
func
(
g
*
G1
)
One
()
*
PointG1
{
p
:=
&
PointG1
{}
return
p
.
Set
(
&
g1One
)
}
// IsZero returns true if given point is equal to zero.
func
(
g
*
G1
)
IsZero
(
p
*
PointG1
)
bool
{
return
p
[
2
]
.
isZero
()
}
// Equal checks if given two G1 point is equal in their affine form.
func
(
g
*
G1
)
Equal
(
p1
,
p2
*
PointG1
)
bool
{
if
g
.
IsZero
(
p1
)
{
return
g
.
IsZero
(
p2
)
}
if
g
.
IsZero
(
p2
)
{
return
g
.
IsZero
(
p1
)
}
t
:=
g
.
t
square
(
t
[
0
],
&
p1
[
2
])
square
(
t
[
1
],
&
p2
[
2
])
mul
(
t
[
2
],
t
[
0
],
&
p2
[
0
])
mul
(
t
[
3
],
t
[
1
],
&
p1
[
0
])
mul
(
t
[
0
],
t
[
0
],
&
p1
[
2
])
mul
(
t
[
1
],
t
[
1
],
&
p2
[
2
])
mul
(
t
[
1
],
t
[
1
],
&
p1
[
1
])
mul
(
t
[
0
],
t
[
0
],
&
p2
[
1
])
return
t
[
0
]
.
equal
(
t
[
1
])
&&
t
[
2
]
.
equal
(
t
[
3
])
}
// InCorrectSubgroup checks whether given point is in correct subgroup.
func
(
g
*
G1
)
InCorrectSubgroup
(
p
*
PointG1
)
bool
{
tmp
:=
&
PointG1
{}
g
.
MulScalar
(
tmp
,
p
,
q
)
return
g
.
IsZero
(
tmp
)
}
// IsOnCurve checks a G1 point is on curve.
func
(
g
*
G1
)
IsOnCurve
(
p
*
PointG1
)
bool
{
if
g
.
IsZero
(
p
)
{
return
true
}
t
:=
g
.
t
square
(
t
[
0
],
&
p
[
1
])
square
(
t
[
1
],
&
p
[
0
])
mul
(
t
[
1
],
t
[
1
],
&
p
[
0
])
square
(
t
[
2
],
&
p
[
2
])
square
(
t
[
3
],
t
[
2
])
mul
(
t
[
2
],
t
[
2
],
t
[
3
])
mul
(
t
[
2
],
b
,
t
[
2
])
add
(
t
[
1
],
t
[
1
],
t
[
2
])
return
t
[
0
]
.
equal
(
t
[
1
])
}
// IsAffine checks a G1 point whether it is in affine form.
func
(
g
*
G1
)
IsAffine
(
p
*
PointG1
)
bool
{
return
p
[
2
]
.
isOne
()
}
// Add adds two G1 points p1, p2 and assigns the result to point at first argument.
func
(
g
*
G1
)
Affine
(
p
*
PointG1
)
*
PointG1
{
if
g
.
IsZero
(
p
)
{
return
p
}
if
!
g
.
IsAffine
(
p
)
{
t
:=
g
.
t
inverse
(
t
[
0
],
&
p
[
2
])
square
(
t
[
1
],
t
[
0
])
mul
(
&
p
[
0
],
&
p
[
0
],
t
[
1
])
mul
(
t
[
0
],
t
[
0
],
t
[
1
])
mul
(
&
p
[
1
],
&
p
[
1
],
t
[
0
])
p
[
2
]
.
one
()
}
return
p
}
// Add adds two G1 points p1, p2 and assigns the result to point at first argument.
func
(
g
*
G1
)
Add
(
r
,
p1
,
p2
*
PointG1
)
*
PointG1
{
// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#addition-add-2007-bl
if
g
.
IsZero
(
p1
)
{
return
r
.
Set
(
p2
)
}
if
g
.
IsZero
(
p2
)
{
return
r
.
Set
(
p1
)
}
t
:=
g
.
t
square
(
t
[
7
],
&
p1
[
2
])
mul
(
t
[
1
],
&
p2
[
0
],
t
[
7
])
mul
(
t
[
2
],
&
p1
[
2
],
t
[
7
])
mul
(
t
[
0
],
&
p2
[
1
],
t
[
2
])
square
(
t
[
8
],
&
p2
[
2
])
mul
(
t
[
3
],
&
p1
[
0
],
t
[
8
])
mul
(
t
[
4
],
&
p2
[
2
],
t
[
8
])
mul
(
t
[
2
],
&
p1
[
1
],
t
[
4
])
if
t
[
1
]
.
equal
(
t
[
3
])
{
if
t
[
0
]
.
equal
(
t
[
2
])
{
return
g
.
Double
(
r
,
p1
)
}
return
r
.
Zero
()
}
sub
(
t
[
1
],
t
[
1
],
t
[
3
])
double
(
t
[
4
],
t
[
1
])
square
(
t
[
4
],
t
[
4
])
mul
(
t
[
5
],
t
[
1
],
t
[
4
])
sub
(
t
[
0
],
t
[
0
],
t
[
2
])
double
(
t
[
0
],
t
[
0
])
square
(
t
[
6
],
t
[
0
])
sub
(
t
[
6
],
t
[
6
],
t
[
5
])
mul
(
t
[
3
],
t
[
3
],
t
[
4
])
double
(
t
[
4
],
t
[
3
])
sub
(
&
r
[
0
],
t
[
6
],
t
[
4
])
sub
(
t
[
4
],
t
[
3
],
&
r
[
0
])
mul
(
t
[
6
],
t
[
2
],
t
[
5
])
double
(
t
[
6
],
t
[
6
])
mul
(
t
[
0
],
t
[
0
],
t
[
4
])
sub
(
&
r
[
1
],
t
[
0
],
t
[
6
])
add
(
t
[
0
],
&
p1
[
2
],
&
p2
[
2
])
square
(
t
[
0
],
t
[
0
])
sub
(
t
[
0
],
t
[
0
],
t
[
7
])
sub
(
t
[
0
],
t
[
0
],
t
[
8
])
mul
(
&
r
[
2
],
t
[
0
],
t
[
1
])
return
r
}
// Double doubles a G1 point p and assigns the result to the point at first argument.
func
(
g
*
G1
)
Double
(
r
,
p
*
PointG1
)
*
PointG1
{
// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
if
g
.
IsZero
(
p
)
{
return
r
.
Set
(
p
)
}
t
:=
g
.
t
square
(
t
[
0
],
&
p
[
0
])
square
(
t
[
1
],
&
p
[
1
])
square
(
t
[
2
],
t
[
1
])
add
(
t
[
1
],
&
p
[
0
],
t
[
1
])
square
(
t
[
1
],
t
[
1
])
sub
(
t
[
1
],
t
[
1
],
t
[
0
])
sub
(
t
[
1
],
t
[
1
],
t
[
2
])
double
(
t
[
1
],
t
[
1
])
double
(
t
[
3
],
t
[
0
])
add
(
t
[
0
],
t
[
3
],
t
[
0
])
square
(
t
[
4
],
t
[
0
])
double
(
t
[
3
],
t
[
1
])
sub
(
&
r
[
0
],
t
[
4
],
t
[
3
])
sub
(
t
[
1
],
t
[
1
],
&
r
[
0
])
double
(
t
[
2
],
t
[
2
])
double
(
t
[
2
],
t
[
2
])
double
(
t
[
2
],
t
[
2
])
mul
(
t
[
0
],
t
[
0
],
t
[
1
])
sub
(
t
[
1
],
t
[
0
],
t
[
2
])
mul
(
t
[
0
],
&
p
[
1
],
&
p
[
2
])
r
[
1
]
.
set
(
t
[
1
])
double
(
&
r
[
2
],
t
[
0
])
return
r
}
// Neg negates a G1 point p and assigns the result to the point at first argument.
func
(
g
*
G1
)
Neg
(
r
,
p
*
PointG1
)
*
PointG1
{
r
[
0
]
.
set
(
&
p
[
0
])
r
[
2
]
.
set
(
&
p
[
2
])
neg
(
&
r
[
1
],
&
p
[
1
])
return
r
}
// Sub subtracts two G1 points p1, p2 and assigns the result to point at first argument.
func
(
g
*
G1
)
Sub
(
c
,
a
,
b
*
PointG1
)
*
PointG1
{
d
:=
&
PointG1
{}
g
.
Neg
(
d
,
b
)
g
.
Add
(
c
,
a
,
d
)
return
c
}
// MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument.
func
(
g
*
G1
)
MulScalar
(
c
,
p
*
PointG1
,
e
*
big
.
Int
)
*
PointG1
{
q
,
n
:=
&
PointG1
{},
&
PointG1
{}
n
.
Set
(
p
)
l
:=
e
.
BitLen
()
for
i
:=
0
;
i
<
l
;
i
++
{
if
e
.
Bit
(
i
)
==
1
{
g
.
Add
(
q
,
q
,
n
)
}
g
.
Double
(
n
,
n
)
}
return
c
.
Set
(
q
)
}
// ClearCofactor maps given a G1 point to correct subgroup
func
(
g
*
G1
)
ClearCofactor
(
p
*
PointG1
)
{
g
.
MulScalar
(
p
,
p
,
cofactorEFFG1
)
}
// MultiExp calculates multi exponentiation. Given pairs of G1 point and scalar values
// (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n
// Length of points and scalars are expected to be equal, otherwise an error is returned.
// Result is assigned to point at first argument.
func
(
g
*
G1
)
MultiExp
(
r
*
PointG1
,
points
[]
*
PointG1
,
powers
[]
*
big
.
Int
)
(
*
PointG1
,
error
)
{
if
len
(
points
)
!=
len
(
powers
)
{
return
nil
,
errors
.
New
(
"point and scalar vectors should be in same length"
)
}
var
c
uint32
=
3
if
len
(
powers
)
>=
32
{
c
=
uint32
(
math
.
Ceil
(
math
.
Log10
(
float64
(
len
(
powers
)))))
}
bucketSize
,
numBits
:=
(
1
<<
c
)
-
1
,
uint32
(
g
.
Q
()
.
BitLen
())
windows
:=
make
([]
*
PointG1
,
numBits
/
c
+
1
)
bucket
:=
make
([]
*
PointG1
,
bucketSize
)
acc
,
sum
:=
g
.
New
(),
g
.
New
()
for
i
:=
0
;
i
<
bucketSize
;
i
++
{
bucket
[
i
]
=
g
.
New
()
}
mask
:=
(
uint64
(
1
)
<<
c
)
-
1
j
:=
0
var
cur
uint32
for
cur
<=
numBits
{
acc
.
Zero
()
bucket
=
make
([]
*
PointG1
,
(
1
<<
c
)
-
1
)
for
i
:=
0
;
i
<
len
(
bucket
);
i
++
{
bucket
[
i
]
=
g
.
New
()
}
for
i
:=
0
;
i
<
len
(
powers
);
i
++
{
s0
:=
powers
[
i
]
.
Uint64
()
index
:=
uint
(
s0
&
mask
)
if
index
!=
0
{
g
.
Add
(
bucket
[
index
-
1
],
bucket
[
index
-
1
],
points
[
i
])
}
powers
[
i
]
=
new
(
big
.
Int
)
.
Rsh
(
powers
[
i
],
uint
(
c
))
}
sum
.
Zero
()
for
i
:=
len
(
bucket
)
-
1
;
i
>=
0
;
i
--
{
g
.
Add
(
sum
,
sum
,
bucket
[
i
])
g
.
Add
(
acc
,
acc
,
sum
)
}
windows
[
j
]
=
g
.
New
()
windows
[
j
]
.
Set
(
acc
)
j
++
cur
+=
c
}
acc
.
Zero
()
for
i
:=
len
(
windows
)
-
1
;
i
>=
0
;
i
--
{
for
j
:=
uint32
(
0
);
j
<
c
;
j
++
{
g
.
Double
(
acc
,
acc
)
}
g
.
Add
(
acc
,
acc
,
windows
[
i
])
}
return
r
.
Set
(
acc
),
nil
}
// MapToCurve given a byte slice returns a valid G1 point.
// This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method.
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06
// Input byte slice should be a valid field element, otherwise an error is returned.
func
(
g
*
G1
)
MapToCurve
(
in
[]
byte
)
(
*
PointG1
,
error
)
{
u
,
err
:=
fromBytes
(
in
)
if
err
!=
nil
{
return
nil
,
err
}
x
,
y
:=
swuMapG1
(
u
)
isogenyMapG1
(
x
,
y
)
one
:=
new
(
fe
)
.
one
()
p
:=
&
PointG1
{
*
x
,
*
y
,
*
one
}
g
.
ClearCofactor
(
p
)
return
g
.
Affine
(
p
),
nil
}
minigeth/crypto/bls12381/g2.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"errors"
"math"
"math/big"
)
// PointG2 is type for point in G2.
// PointG2 is both used for Affine and Jacobian point representation.
// If z is equal to one the point is considered as in affine form.
type
PointG2
[
3
]
fe2
// Set copies valeus of one point to another.
func
(
p
*
PointG2
)
Set
(
p2
*
PointG2
)
*
PointG2
{
p
[
0
]
.
set
(
&
p2
[
0
])
p
[
1
]
.
set
(
&
p2
[
1
])
p
[
2
]
.
set
(
&
p2
[
2
])
return
p
}
// Zero returns G2 point in point at infinity representation
func
(
p
*
PointG2
)
Zero
()
*
PointG2
{
p
[
0
]
.
zero
()
p
[
1
]
.
one
()
p
[
2
]
.
zero
()
return
p
}
type
tempG2
struct
{
t
[
9
]
*
fe2
}
// G2 is struct for G2 group.
type
G2
struct
{
f
*
fp2
tempG2
}
// NewG2 constructs a new G2 instance.
func
NewG2
()
*
G2
{
return
newG2
(
nil
)
}
func
newG2
(
f
*
fp2
)
*
G2
{
if
f
==
nil
{
f
=
newFp2
()
}
t
:=
newTempG2
()
return
&
G2
{
f
,
t
}
}
func
newTempG2
()
tempG2
{
t
:=
[
9
]
*
fe2
{}
for
i
:=
0
;
i
<
9
;
i
++
{
t
[
i
]
=
&
fe2
{}
}
return
tempG2
{
t
}
}
// Q returns group order in big.Int.
func
(
g
*
G2
)
Q
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
q
)
}
func
(
g
*
G2
)
fromBytesUnchecked
(
in
[]
byte
)
(
*
PointG2
,
error
)
{
p0
,
err
:=
g
.
f
.
fromBytes
(
in
[
:
96
])
if
err
!=
nil
{
return
nil
,
err
}
p1
,
err
:=
g
.
f
.
fromBytes
(
in
[
96
:
])
if
err
!=
nil
{
return
nil
,
err
}
p2
:=
new
(
fe2
)
.
one
()
return
&
PointG2
{
*
p0
,
*
p1
,
*
p2
},
nil
}
// FromBytes constructs a new point given uncompressed byte input.
// FromBytes does not take zcash flags into account.
// Byte input expected to be larger than 96 bytes.
// First 192 bytes should be concatenation of x and y values
// Point (0, 0) is considered as infinity.
func
(
g
*
G2
)
FromBytes
(
in
[]
byte
)
(
*
PointG2
,
error
)
{
if
len
(
in
)
!=
192
{
return
nil
,
errors
.
New
(
"input string should be equal or larger than 192"
)
}
p0
,
err
:=
g
.
f
.
fromBytes
(
in
[
:
96
])
if
err
!=
nil
{
return
nil
,
err
}
p1
,
err
:=
g
.
f
.
fromBytes
(
in
[
96
:
])
if
err
!=
nil
{
return
nil
,
err
}
// check if given input points to infinity
if
p0
.
isZero
()
&&
p1
.
isZero
()
{
return
g
.
Zero
(),
nil
}
p2
:=
new
(
fe2
)
.
one
()
p
:=
&
PointG2
{
*
p0
,
*
p1
,
*
p2
}
if
!
g
.
IsOnCurve
(
p
)
{
return
nil
,
errors
.
New
(
"point is not on curve"
)
}
return
p
,
nil
}
// DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G1 Point.
func
(
g
*
G2
)
DecodePoint
(
in
[]
byte
)
(
*
PointG2
,
error
)
{
if
len
(
in
)
!=
256
{
return
nil
,
errors
.
New
(
"invalid g2 point length"
)
}
pointBytes
:=
make
([]
byte
,
192
)
x0Bytes
,
err
:=
decodeFieldElement
(
in
[
:
64
])
if
err
!=
nil
{
return
nil
,
err
}
x1Bytes
,
err
:=
decodeFieldElement
(
in
[
64
:
128
])
if
err
!=
nil
{
return
nil
,
err
}
y0Bytes
,
err
:=
decodeFieldElement
(
in
[
128
:
192
])
if
err
!=
nil
{
return
nil
,
err
}
y1Bytes
,
err
:=
decodeFieldElement
(
in
[
192
:
])
if
err
!=
nil
{
return
nil
,
err
}
copy
(
pointBytes
[
:
48
],
x1Bytes
)
copy
(
pointBytes
[
48
:
96
],
x0Bytes
)
copy
(
pointBytes
[
96
:
144
],
y1Bytes
)
copy
(
pointBytes
[
144
:
192
],
y0Bytes
)
return
g
.
FromBytes
(
pointBytes
)
}
// ToBytes serializes a point into bytes in uncompressed form,
// does not take zcash flags into account,
// returns (0, 0) if point is infinity.
func
(
g
*
G2
)
ToBytes
(
p
*
PointG2
)
[]
byte
{
out
:=
make
([]
byte
,
192
)
if
g
.
IsZero
(
p
)
{
return
out
}
g
.
Affine
(
p
)
copy
(
out
[
:
96
],
g
.
f
.
toBytes
(
&
p
[
0
]))
copy
(
out
[
96
:
],
g
.
f
.
toBytes
(
&
p
[
1
]))
return
out
}
// EncodePoint encodes a point into 256 bytes.
func
(
g
*
G2
)
EncodePoint
(
p
*
PointG2
)
[]
byte
{
// outRaw is 96 bytes
outRaw
:=
g
.
ToBytes
(
p
)
out
:=
make
([]
byte
,
256
)
// encode x
copy
(
out
[
16
:
16
+
48
],
outRaw
[
48
:
96
])
copy
(
out
[
80
:
80
+
48
],
outRaw
[
:
48
])
// encode y
copy
(
out
[
144
:
144
+
48
],
outRaw
[
144
:
])
copy
(
out
[
208
:
208
+
48
],
outRaw
[
96
:
144
])
return
out
}
// New creates a new G2 Point which is equal to zero in other words point at infinity.
func
(
g
*
G2
)
New
()
*
PointG2
{
return
new
(
PointG2
)
.
Zero
()
}
// Zero returns a new G2 Point which is equal to point at infinity.
func
(
g
*
G2
)
Zero
()
*
PointG2
{
return
new
(
PointG2
)
.
Zero
()
}
// One returns a new G2 Point which is equal to generator point.
func
(
g
*
G2
)
One
()
*
PointG2
{
p
:=
&
PointG2
{}
return
p
.
Set
(
&
g2One
)
}
// IsZero returns true if given point is equal to zero.
func
(
g
*
G2
)
IsZero
(
p
*
PointG2
)
bool
{
return
p
[
2
]
.
isZero
()
}
// Equal checks if given two G2 point is equal in their affine form.
func
(
g
*
G2
)
Equal
(
p1
,
p2
*
PointG2
)
bool
{
if
g
.
IsZero
(
p1
)
{
return
g
.
IsZero
(
p2
)
}
if
g
.
IsZero
(
p2
)
{
return
g
.
IsZero
(
p1
)
}
t
:=
g
.
t
g
.
f
.
square
(
t
[
0
],
&
p1
[
2
])
g
.
f
.
square
(
t
[
1
],
&
p2
[
2
])
g
.
f
.
mul
(
t
[
2
],
t
[
0
],
&
p2
[
0
])
g
.
f
.
mul
(
t
[
3
],
t
[
1
],
&
p1
[
0
])
g
.
f
.
mul
(
t
[
0
],
t
[
0
],
&
p1
[
2
])
g
.
f
.
mul
(
t
[
1
],
t
[
1
],
&
p2
[
2
])
g
.
f
.
mul
(
t
[
1
],
t
[
1
],
&
p1
[
1
])
g
.
f
.
mul
(
t
[
0
],
t
[
0
],
&
p2
[
1
])
return
t
[
0
]
.
equal
(
t
[
1
])
&&
t
[
2
]
.
equal
(
t
[
3
])
}
// InCorrectSubgroup checks whether given point is in correct subgroup.
func
(
g
*
G2
)
InCorrectSubgroup
(
p
*
PointG2
)
bool
{
tmp
:=
&
PointG2
{}
g
.
MulScalar
(
tmp
,
p
,
q
)
return
g
.
IsZero
(
tmp
)
}
// IsOnCurve checks a G2 point is on curve.
func
(
g
*
G2
)
IsOnCurve
(
p
*
PointG2
)
bool
{
if
g
.
IsZero
(
p
)
{
return
true
}
t
:=
g
.
t
g
.
f
.
square
(
t
[
0
],
&
p
[
1
])
g
.
f
.
square
(
t
[
1
],
&
p
[
0
])
g
.
f
.
mul
(
t
[
1
],
t
[
1
],
&
p
[
0
])
g
.
f
.
square
(
t
[
2
],
&
p
[
2
])
g
.
f
.
square
(
t
[
3
],
t
[
2
])
g
.
f
.
mul
(
t
[
2
],
t
[
2
],
t
[
3
])
g
.
f
.
mul
(
t
[
2
],
b2
,
t
[
2
])
g
.
f
.
add
(
t
[
1
],
t
[
1
],
t
[
2
])
return
t
[
0
]
.
equal
(
t
[
1
])
}
// IsAffine checks a G2 point whether it is in affine form.
func
(
g
*
G2
)
IsAffine
(
p
*
PointG2
)
bool
{
return
p
[
2
]
.
isOne
()
}
// Affine calculates affine form of given G2 point.
func
(
g
*
G2
)
Affine
(
p
*
PointG2
)
*
PointG2
{
if
g
.
IsZero
(
p
)
{
return
p
}
if
!
g
.
IsAffine
(
p
)
{
t
:=
g
.
t
g
.
f
.
inverse
(
t
[
0
],
&
p
[
2
])
g
.
f
.
square
(
t
[
1
],
t
[
0
])
g
.
f
.
mul
(
&
p
[
0
],
&
p
[
0
],
t
[
1
])
g
.
f
.
mul
(
t
[
0
],
t
[
0
],
t
[
1
])
g
.
f
.
mul
(
&
p
[
1
],
&
p
[
1
],
t
[
0
])
p
[
2
]
.
one
()
}
return
p
}
// Add adds two G2 points p1, p2 and assigns the result to point at first argument.
func
(
g
*
G2
)
Add
(
r
,
p1
,
p2
*
PointG2
)
*
PointG2
{
// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#addition-add-2007-bl
if
g
.
IsZero
(
p1
)
{
return
r
.
Set
(
p2
)
}
if
g
.
IsZero
(
p2
)
{
return
r
.
Set
(
p1
)
}
t
:=
g
.
t
g
.
f
.
square
(
t
[
7
],
&
p1
[
2
])
g
.
f
.
mul
(
t
[
1
],
&
p2
[
0
],
t
[
7
])
g
.
f
.
mul
(
t
[
2
],
&
p1
[
2
],
t
[
7
])
g
.
f
.
mul
(
t
[
0
],
&
p2
[
1
],
t
[
2
])
g
.
f
.
square
(
t
[
8
],
&
p2
[
2
])
g
.
f
.
mul
(
t
[
3
],
&
p1
[
0
],
t
[
8
])
g
.
f
.
mul
(
t
[
4
],
&
p2
[
2
],
t
[
8
])
g
.
f
.
mul
(
t
[
2
],
&
p1
[
1
],
t
[
4
])
if
t
[
1
]
.
equal
(
t
[
3
])
{
if
t
[
0
]
.
equal
(
t
[
2
])
{
return
g
.
Double
(
r
,
p1
)
}
return
r
.
Zero
()
}
g
.
f
.
sub
(
t
[
1
],
t
[
1
],
t
[
3
])
g
.
f
.
double
(
t
[
4
],
t
[
1
])
g
.
f
.
square
(
t
[
4
],
t
[
4
])
g
.
f
.
mul
(
t
[
5
],
t
[
1
],
t
[
4
])
g
.
f
.
sub
(
t
[
0
],
t
[
0
],
t
[
2
])
g
.
f
.
double
(
t
[
0
],
t
[
0
])
g
.
f
.
square
(
t
[
6
],
t
[
0
])
g
.
f
.
sub
(
t
[
6
],
t
[
6
],
t
[
5
])
g
.
f
.
mul
(
t
[
3
],
t
[
3
],
t
[
4
])
g
.
f
.
double
(
t
[
4
],
t
[
3
])
g
.
f
.
sub
(
&
r
[
0
],
t
[
6
],
t
[
4
])
g
.
f
.
sub
(
t
[
4
],
t
[
3
],
&
r
[
0
])
g
.
f
.
mul
(
t
[
6
],
t
[
2
],
t
[
5
])
g
.
f
.
double
(
t
[
6
],
t
[
6
])
g
.
f
.
mul
(
t
[
0
],
t
[
0
],
t
[
4
])
g
.
f
.
sub
(
&
r
[
1
],
t
[
0
],
t
[
6
])
g
.
f
.
add
(
t
[
0
],
&
p1
[
2
],
&
p2
[
2
])
g
.
f
.
square
(
t
[
0
],
t
[
0
])
g
.
f
.
sub
(
t
[
0
],
t
[
0
],
t
[
7
])
g
.
f
.
sub
(
t
[
0
],
t
[
0
],
t
[
8
])
g
.
f
.
mul
(
&
r
[
2
],
t
[
0
],
t
[
1
])
return
r
}
// Double doubles a G2 point p and assigns the result to the point at first argument.
func
(
g
*
G2
)
Double
(
r
,
p
*
PointG2
)
*
PointG2
{
// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
if
g
.
IsZero
(
p
)
{
return
r
.
Set
(
p
)
}
t
:=
g
.
t
g
.
f
.
square
(
t
[
0
],
&
p
[
0
])
g
.
f
.
square
(
t
[
1
],
&
p
[
1
])
g
.
f
.
square
(
t
[
2
],
t
[
1
])
g
.
f
.
add
(
t
[
1
],
&
p
[
0
],
t
[
1
])
g
.
f
.
square
(
t
[
1
],
t
[
1
])
g
.
f
.
sub
(
t
[
1
],
t
[
1
],
t
[
0
])
g
.
f
.
sub
(
t
[
1
],
t
[
1
],
t
[
2
])
g
.
f
.
double
(
t
[
1
],
t
[
1
])
g
.
f
.
double
(
t
[
3
],
t
[
0
])
g
.
f
.
add
(
t
[
0
],
t
[
3
],
t
[
0
])
g
.
f
.
square
(
t
[
4
],
t
[
0
])
g
.
f
.
double
(
t
[
3
],
t
[
1
])
g
.
f
.
sub
(
&
r
[
0
],
t
[
4
],
t
[
3
])
g
.
f
.
sub
(
t
[
1
],
t
[
1
],
&
r
[
0
])
g
.
f
.
double
(
t
[
2
],
t
[
2
])
g
.
f
.
double
(
t
[
2
],
t
[
2
])
g
.
f
.
double
(
t
[
2
],
t
[
2
])
g
.
f
.
mul
(
t
[
0
],
t
[
0
],
t
[
1
])
g
.
f
.
sub
(
t
[
1
],
t
[
0
],
t
[
2
])
g
.
f
.
mul
(
t
[
0
],
&
p
[
1
],
&
p
[
2
])
r
[
1
]
.
set
(
t
[
1
])
g
.
f
.
double
(
&
r
[
2
],
t
[
0
])
return
r
}
// Neg negates a G2 point p and assigns the result to the point at first argument.
func
(
g
*
G2
)
Neg
(
r
,
p
*
PointG2
)
*
PointG2
{
r
[
0
]
.
set
(
&
p
[
0
])
g
.
f
.
neg
(
&
r
[
1
],
&
p
[
1
])
r
[
2
]
.
set
(
&
p
[
2
])
return
r
}
// Sub subtracts two G2 points p1, p2 and assigns the result to point at first argument.
func
(
g
*
G2
)
Sub
(
c
,
a
,
b
*
PointG2
)
*
PointG2
{
d
:=
&
PointG2
{}
g
.
Neg
(
d
,
b
)
g
.
Add
(
c
,
a
,
d
)
return
c
}
// MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument.
func
(
g
*
G2
)
MulScalar
(
c
,
p
*
PointG2
,
e
*
big
.
Int
)
*
PointG2
{
q
,
n
:=
&
PointG2
{},
&
PointG2
{}
n
.
Set
(
p
)
l
:=
e
.
BitLen
()
for
i
:=
0
;
i
<
l
;
i
++
{
if
e
.
Bit
(
i
)
==
1
{
g
.
Add
(
q
,
q
,
n
)
}
g
.
Double
(
n
,
n
)
}
return
c
.
Set
(
q
)
}
// ClearCofactor maps given a G2 point to correct subgroup
func
(
g
*
G2
)
ClearCofactor
(
p
*
PointG2
)
{
g
.
MulScalar
(
p
,
p
,
cofactorEFFG2
)
}
// MultiExp calculates multi exponentiation. Given pairs of G2 point and scalar values
// (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n
// Length of points and scalars are expected to be equal, otherwise an error is returned.
// Result is assigned to point at first argument.
func
(
g
*
G2
)
MultiExp
(
r
*
PointG2
,
points
[]
*
PointG2
,
powers
[]
*
big
.
Int
)
(
*
PointG2
,
error
)
{
if
len
(
points
)
!=
len
(
powers
)
{
return
nil
,
errors
.
New
(
"point and scalar vectors should be in same length"
)
}
var
c
uint32
=
3
if
len
(
powers
)
>=
32
{
c
=
uint32
(
math
.
Ceil
(
math
.
Log10
(
float64
(
len
(
powers
)))))
}
bucketSize
,
numBits
:=
(
1
<<
c
)
-
1
,
uint32
(
g
.
Q
()
.
BitLen
())
windows
:=
make
([]
*
PointG2
,
numBits
/
c
+
1
)
bucket
:=
make
([]
*
PointG2
,
bucketSize
)
acc
,
sum
:=
g
.
New
(),
g
.
New
()
for
i
:=
0
;
i
<
bucketSize
;
i
++
{
bucket
[
i
]
=
g
.
New
()
}
mask
:=
(
uint64
(
1
)
<<
c
)
-
1
j
:=
0
var
cur
uint32
for
cur
<=
numBits
{
acc
.
Zero
()
bucket
=
make
([]
*
PointG2
,
(
1
<<
c
)
-
1
)
for
i
:=
0
;
i
<
len
(
bucket
);
i
++
{
bucket
[
i
]
=
g
.
New
()
}
for
i
:=
0
;
i
<
len
(
powers
);
i
++
{
s0
:=
powers
[
i
]
.
Uint64
()
index
:=
uint
(
s0
&
mask
)
if
index
!=
0
{
g
.
Add
(
bucket
[
index
-
1
],
bucket
[
index
-
1
],
points
[
i
])
}
powers
[
i
]
=
new
(
big
.
Int
)
.
Rsh
(
powers
[
i
],
uint
(
c
))
}
sum
.
Zero
()
for
i
:=
len
(
bucket
)
-
1
;
i
>=
0
;
i
--
{
g
.
Add
(
sum
,
sum
,
bucket
[
i
])
g
.
Add
(
acc
,
acc
,
sum
)
}
windows
[
j
]
=
g
.
New
()
windows
[
j
]
.
Set
(
acc
)
j
++
cur
+=
c
}
acc
.
Zero
()
for
i
:=
len
(
windows
)
-
1
;
i
>=
0
;
i
--
{
for
j
:=
uint32
(
0
);
j
<
c
;
j
++
{
g
.
Double
(
acc
,
acc
)
}
g
.
Add
(
acc
,
acc
,
windows
[
i
])
}
return
r
.
Set
(
acc
),
nil
}
// MapToCurve given a byte slice returns a valid G2 point.
// This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method.
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-05#section-6.6.2
// Input byte slice should be a valid field element, otherwise an error is returned.
func
(
g
*
G2
)
MapToCurve
(
in
[]
byte
)
(
*
PointG2
,
error
)
{
fp2
:=
g
.
f
u
,
err
:=
fp2
.
fromBytes
(
in
)
if
err
!=
nil
{
return
nil
,
err
}
x
,
y
:=
swuMapG2
(
fp2
,
u
)
isogenyMapG2
(
fp2
,
x
,
y
)
z
:=
new
(
fe2
)
.
one
()
q
:=
&
PointG2
{
*
x
,
*
y
,
*
z
}
g
.
ClearCofactor
(
q
)
return
g
.
Affine
(
q
),
nil
}
minigeth/crypto/bls12381/gt.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"errors"
"math/big"
)
// E is type for target group element
type
E
=
fe12
// GT is type for target multiplicative group GT.
type
GT
struct
{
fp12
*
fp12
}
func
(
e
*
E
)
Set
(
e2
*
E
)
*
E
{
return
e
.
set
(
e2
)
}
// One sets a new target group element to one
func
(
e
*
E
)
One
()
*
E
{
e
=
new
(
fe12
)
.
one
()
return
e
}
// IsOne returns true if given element equals to one
func
(
e
*
E
)
IsOne
()
bool
{
return
e
.
isOne
()
}
// Equal returns true if given two element is equal, otherwise returns false
func
(
g
*
E
)
Equal
(
g2
*
E
)
bool
{
return
g
.
equal
(
g2
)
}
// NewGT constructs new target group instance.
func
NewGT
()
*
GT
{
fp12
:=
newFp12
(
nil
)
return
&
GT
{
fp12
}
}
// Q returns group order in big.Int.
func
(
g
*
GT
)
Q
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
q
)
}
// FromBytes expects 576 byte input and returns target group element
// FromBytes returns error if given element is not on correct subgroup.
func
(
g
*
GT
)
FromBytes
(
in
[]
byte
)
(
*
E
,
error
)
{
e
,
err
:=
g
.
fp12
.
fromBytes
(
in
)
if
err
!=
nil
{
return
nil
,
err
}
if
!
g
.
IsValid
(
e
)
{
return
e
,
errors
.
New
(
"invalid element"
)
}
return
e
,
nil
}
// ToBytes serializes target group element.
func
(
g
*
GT
)
ToBytes
(
e
*
E
)
[]
byte
{
return
g
.
fp12
.
toBytes
(
e
)
}
// IsValid checks whether given target group element is in correct subgroup.
func
(
g
*
GT
)
IsValid
(
e
*
E
)
bool
{
r
:=
g
.
New
()
g
.
fp12
.
exp
(
r
,
e
,
q
)
return
r
.
isOne
()
}
// New initializes a new target group element which is equal to one
func
(
g
*
GT
)
New
()
*
E
{
return
new
(
E
)
.
One
()
}
// Add adds two field element `a` and `b` and assigns the result to the element in first argument.
func
(
g
*
GT
)
Add
(
c
,
a
,
b
*
E
)
{
g
.
fp12
.
add
(
c
,
a
,
b
)
}
// Sub subtracts two field element `a` and `b`, and assigns the result to the element in first argument.
func
(
g
*
GT
)
Sub
(
c
,
a
,
b
*
E
)
{
g
.
fp12
.
sub
(
c
,
a
,
b
)
}
// Mul multiplies two field element `a` and `b` and assigns the result to the element in first argument.
func
(
g
*
GT
)
Mul
(
c
,
a
,
b
*
E
)
{
g
.
fp12
.
mul
(
c
,
a
,
b
)
}
// Square squares an element `a` and assigns the result to the element in first argument.
func
(
g
*
GT
)
Square
(
c
,
a
*
E
)
{
g
.
fp12
.
cyclotomicSquare
(
c
,
a
)
}
// Exp exponents an element `a` by a scalar `s` and assigns the result to the element in first argument.
func
(
g
*
GT
)
Exp
(
c
,
a
*
E
,
s
*
big
.
Int
)
{
g
.
fp12
.
cyclotomicExp
(
c
,
a
,
s
)
}
// Inverse inverses an element `a` and assigns the result to the element in first argument.
func
(
g
*
GT
)
Inverse
(
c
,
a
*
E
)
{
g
.
fp12
.
inverse
(
c
,
a
)
}
minigeth/crypto/bls12381/isogeny.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
// isogenyMapG1 applies 11-isogeny map for BLS12-381 G1 defined at draft-irtf-cfrg-hash-to-curve-06.
func
isogenyMapG1
(
x
,
y
*
fe
)
{
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-C.2
params
:=
isogenyConstansG1
degree
:=
15
xNum
,
xDen
,
yNum
,
yDen
:=
new
(
fe
),
new
(
fe
),
new
(
fe
),
new
(
fe
)
xNum
.
set
(
params
[
0
][
degree
])
xDen
.
set
(
params
[
1
][
degree
])
yNum
.
set
(
params
[
2
][
degree
])
yDen
.
set
(
params
[
3
][
degree
])
for
i
:=
degree
-
1
;
i
>=
0
;
i
--
{
mul
(
xNum
,
xNum
,
x
)
mul
(
xDen
,
xDen
,
x
)
mul
(
yNum
,
yNum
,
x
)
mul
(
yDen
,
yDen
,
x
)
add
(
xNum
,
xNum
,
params
[
0
][
i
])
add
(
xDen
,
xDen
,
params
[
1
][
i
])
add
(
yNum
,
yNum
,
params
[
2
][
i
])
add
(
yDen
,
yDen
,
params
[
3
][
i
])
}
inverse
(
xDen
,
xDen
)
inverse
(
yDen
,
yDen
)
mul
(
xNum
,
xNum
,
xDen
)
mul
(
yNum
,
yNum
,
yDen
)
mul
(
yNum
,
yNum
,
y
)
x
.
set
(
xNum
)
y
.
set
(
yNum
)
}
// isogenyMapG2 applies 11-isogeny map for BLS12-381 G1 defined at draft-irtf-cfrg-hash-to-curve-06.
func
isogenyMapG2
(
e
*
fp2
,
x
,
y
*
fe2
)
{
if
e
==
nil
{
e
=
newFp2
()
}
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-C.2
params
:=
isogenyConstantsG2
degree
:=
3
xNum
:=
new
(
fe2
)
.
set
(
params
[
0
][
degree
])
xDen
:=
new
(
fe2
)
.
set
(
params
[
1
][
degree
])
yNum
:=
new
(
fe2
)
.
set
(
params
[
2
][
degree
])
yDen
:=
new
(
fe2
)
.
set
(
params
[
3
][
degree
])
for
i
:=
degree
-
1
;
i
>=
0
;
i
--
{
e
.
mul
(
xNum
,
xNum
,
x
)
e
.
mul
(
xDen
,
xDen
,
x
)
e
.
mul
(
yNum
,
yNum
,
x
)
e
.
mul
(
yDen
,
yDen
,
x
)
e
.
add
(
xNum
,
xNum
,
params
[
0
][
i
])
e
.
add
(
xDen
,
xDen
,
params
[
1
][
i
])
e
.
add
(
yNum
,
yNum
,
params
[
2
][
i
])
e
.
add
(
yDen
,
yDen
,
params
[
3
][
i
])
}
e
.
inverse
(
xDen
,
xDen
)
e
.
inverse
(
yDen
,
yDen
)
e
.
mul
(
xNum
,
xNum
,
xDen
)
e
.
mul
(
yNum
,
yNum
,
yDen
)
e
.
mul
(
yNum
,
yNum
,
y
)
x
.
set
(
xNum
)
y
.
set
(
yNum
)
}
var
isogenyConstansG1
=
[
4
][
16
]
*
fe
{
[
16
]
*
fe
{
&
fe
{
0x4d18b6f3af00131c
,
0x19fa219793fee28c
,
0x3f2885f1467f19ae
,
0x23dcea34f2ffb304
,
0xd15b58d2ffc00054
,
0x0913be200a20bef4
},
&
fe
{
0x898985385cdbbd8b
,
0x3c79e43cc7d966aa
,
0x1597e193f4cd233a
,
0x8637ef1e4d6623ad
,
0x11b22deed20d827b
,
0x07097bc5998784ad
},
&
fe
{
0xa542583a480b664b
,
0xfc7169c026e568c6
,
0x5ba2ef314ed8b5a6
,
0x5b5491c05102f0e7
,
0xdf6e99707d2a0079
,
0x0784151ed7605524
},
&
fe
{
0x494e212870f72741
,
0xab9be52fbda43021
,
0x26f5577994e34c3d
,
0x049dfee82aefbd60
,
0x65dadd7828505289
,
0x0e93d431ea011aeb
},
&
fe
{
0x90ee774bd6a74d45
,
0x7ada1c8a41bfb185
,
0x0f1a8953b325f464
,
0x104c24211be4805c
,
0x169139d319ea7a8f
,
0x09f20ead8e532bf6
},
&
fe
{
0x6ddd93e2f43626b7
,
0xa5482c9aa1ccd7bd
,
0x143245631883f4bd
,
0x2e0a94ccf77ec0db
,
0xb0282d480e56489f
,
0x18f4bfcbb4368929
},
&
fe
{
0x23c5f0c953402dfd
,
0x7a43ff6958ce4fe9
,
0x2c390d3d2da5df63
,
0xd0df5c98e1f9d70f
,
0xffd89869a572b297
,
0x1277ffc72f25e8fe
},
&
fe
{
0x79f4f0490f06a8a6
,
0x85f894a88030fd81
,
0x12da3054b18b6410
,
0xe2a57f6505880d65
,
0xbba074f260e400f1
,
0x08b76279f621d028
},
&
fe
{
0xe67245ba78d5b00b
,
0x8456ba9a1f186475
,
0x7888bff6e6b33bb4
,
0xe21585b9a30f86cb
,
0x05a69cdcef55feee
,
0x09e699dd9adfa5ac
},
&
fe
{
0x0de5c357bff57107
,
0x0a0db4ae6b1a10b2
,
0xe256bb67b3b3cd8d
,
0x8ad456574e9db24f
,
0x0443915f50fd4179
,
0x098c4bf7de8b6375
},
&
fe
{
0xe6b0617e7dd929c7
,
0xfe6e37d442537375
,
0x1dafdeda137a489e
,
0xe4efd1ad3f767ceb
,
0x4a51d8667f0fe1cf
,
0x054fdf4bbf1d821c
},
&
fe
{
0x72db2a50658d767b
,
0x8abf91faa257b3d5
,
0xe969d6833764ab47
,
0x464170142a1009eb
,
0xb14f01aadb30be2f
,
0x18ae6a856f40715d
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
},
[
16
]
*
fe
{
&
fe
{
0xb962a077fdb0f945
,
0xa6a9740fefda13a0
,
0xc14d568c3ed6c544
,
0xb43fc37b908b133e
,
0x9c0b3ac929599016
,
0x0165aa6c93ad115f
},
&
fe
{
0x23279a3ba506c1d9
,
0x92cfca0a9465176a
,
0x3b294ab13755f0ff
,
0x116dda1c5070ae93
,
0xed4530924cec2045
,
0x083383d6ed81f1ce
},
&
fe
{
0x9885c2a6449fecfc
,
0x4a2b54ccd37733f0
,
0x17da9ffd8738c142
,
0xa0fba72732b3fafd
,
0xff364f36e54b6812
,
0x0f29c13c660523e2
},
&
fe
{
0xe349cc118278f041
,
0xd487228f2f3204fb
,
0xc9d325849ade5150
,
0x43a92bd69c15c2df
,
0x1c2c7844bc417be4
,
0x12025184f407440c
},
&
fe
{
0x587f65ae6acb057b
,
0x1444ef325140201f
,
0xfbf995e71270da49
,
0xccda066072436a42
,
0x7408904f0f186bb2
,
0x13b93c63edf6c015
},
&
fe
{
0xfb918622cd141920
,
0x4a4c64423ecaddb4
,
0x0beb232927f7fb26
,
0x30f94df6f83a3dc2
,
0xaeedd424d780f388
,
0x06cc402dd594bbeb
},
&
fe
{
0xd41f761151b23f8f
,
0x32a92465435719b3
,
0x64f436e888c62cb9
,
0xdf70a9a1f757c6e4
,
0x6933a38d5b594c81
,
0x0c6f7f7237b46606
},
&
fe
{
0x693c08747876c8f7
,
0x22c9850bf9cf80f0
,
0x8e9071dab950c124
,
0x89bc62d61c7baf23
,
0xbc6be2d8dad57c23
,
0x17916987aa14a122
},
&
fe
{
0x1be3ff439c1316fd
,
0x9965243a7571dfa7
,
0xc7f7f62962f5cd81
,
0x32c6aa9af394361c
,
0xbbc2ee18e1c227f4
,
0x0c102cbac531bb34
},
&
fe
{
0x997614c97bacbf07
,
0x61f86372b99192c0
,
0x5b8c95fc14353fc3
,
0xca2b066c2a87492f
,
0x16178f5bbf698711
,
0x12a6dcd7f0f4e0e8
},
&
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
&
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
},
[
16
]
*
fe
{
&
fe
{
0x2b567ff3e2837267
,
0x1d4d9e57b958a767
,
0xce028fea04bd7373
,
0xcc31a30a0b6cd3df
,
0x7d7b18a682692693
,
0x0d300744d42a0310
},
&
fe
{
0x99c2555fa542493f
,
0xfe7f53cc4874f878
,
0x5df0608b8f97608a
,
0x14e03832052b49c8
,
0x706326a6957dd5a4
,
0x0a8dadd9c2414555
},
&
fe
{
0x13d942922a5cf63a
,
0x357e33e36e261e7d
,
0xcf05a27c8456088d
,
0x0000bd1de7ba50f0
,
0x83d0c7532f8c1fde
,
0x13f70bf38bbf2905
},
&
fe
{
0x5c57fd95bfafbdbb
,
0x28a359a65e541707
,
0x3983ceb4f6360b6d
,
0xafe19ff6f97e6d53
,
0xb3468f4550192bf7
,
0x0bb6cde49d8ba257
},
&
fe
{
0x590b62c7ff8a513f
,
0x314b4ce372cacefd
,
0x6bef32ce94b8a800
,
0x6ddf84a095713d5f
,
0x64eace4cb0982191
,
0x0386213c651b888d
},
&
fe
{
0xa5310a31111bbcdd
,
0xa14ac0f5da148982
,
0xf9ad9cc95423d2e9
,
0xaa6ec095283ee4a7
,
0xcf5b1f022e1c9107
,
0x01fddf5aed881793
},
&
fe
{
0x65a572b0d7a7d950
,
0xe25c2d8183473a19
,
0xc2fcebe7cb877dbd
,
0x05b2d36c769a89b0
,
0xba12961be86e9efb
,
0x07eb1b29c1dfde1f
},
&
fe
{
0x93e09572f7c4cd24
,
0x364e929076795091
,
0x8569467e68af51b5
,
0xa47da89439f5340f
,
0xf4fa918082e44d64
,
0x0ad52ba3e6695a79
},
&
fe
{
0x911429844e0d5f54
,
0xd03f51a3516bb233
,
0x3d587e5640536e66
,
0xfa86d2a3a9a73482
,
0xa90ed5adf1ed5537
,
0x149c9c326a5e7393
},
&
fe
{
0x462bbeb03c12921a
,
0xdc9af5fa0a274a17
,
0x9a558ebde836ebed
,
0x649ef8f11a4fae46
,
0x8100e1652b3cdc62
,
0x1862bd62c291dacb
},
&
fe
{
0x05c9b8ca89f12c26
,
0x0194160fa9b9ac4f
,
0x6a643d5a6879fa2c
,
0x14665bdd8846e19d
,
0xbb1d0d53af3ff6bf
,
0x12c7e1c3b28962e5
},
&
fe
{
0xb55ebf900b8a3e17
,
0xfedc77ec1a9201c4
,
0x1f07db10ea1a4df4
,
0x0dfbd15dc41a594d
,
0x389547f2334a5391
,
0x02419f98165871a4
},
&
fe
{
0xb416af000745fc20
,
0x8e563e9d1ea6d0f5
,
0x7c763e17763a0652
,
0x01458ef0159ebbef
,
0x8346fe421f96bb13
,
0x0d2d7b829ce324d2
},
&
fe
{
0x93096bb538d64615
,
0x6f2a2619951d823a
,
0x8f66b3ea59514fa4
,
0xf563e63704f7092f
,
0x724b136c4cf2d9fa
,
0x046959cfcfd0bf49
},
&
fe
{
0xea748d4b6e405346
,
0x91e9079c2c02d58f
,
0x41064965946d9b59
,
0xa06731f1d2bbe1ee
,
0x07f897e267a33f1b
,
0x1017290919210e5f
},
&
fe
{
0x872aa6c17d985097
,
0xeecc53161264562a
,
0x07afe37afff55002
,
0x54759078e5be6838
,
0xc4b92d15db8acca8
,
0x106d87d1b51d13b9
},
},
[
16
]
*
fe
{
&
fe
{
0xeb6c359d47e52b1c
,
0x18ef5f8a10634d60
,
0xddfa71a0889d5b7e
,
0x723e71dcc5fc1323
,
0x52f45700b70d5c69
,
0x0a8b981ee47691f1
},
&
fe
{
0x616a3c4f5535b9fb
,
0x6f5f037395dbd911
,
0xf25f4cc5e35c65da
,
0x3e50dffea3c62658
,
0x6a33dca523560776
,
0x0fadeff77b6bfe3e
},
&
fe
{
0x2be9b66df470059c
,
0x24a2c159a3d36742
,
0x115dbe7ad10c2a37
,
0xb6634a652ee5884d
,
0x04fe8bb2b8d81af4
,
0x01c2a7a256fe9c41
},
&
fe
{
0xf27bf8ef3b75a386
,
0x898b367476c9073f
,
0x24482e6b8c2f4e5f
,
0xc8e0bbd6fe110806
,
0x59b0c17f7631448a
,
0x11037cd58b3dbfbd
},
&
fe
{
0x31c7912ea267eec6
,
0x1dbf6f1c5fcdb700
,
0xd30d4fe3ba86fdb1
,
0x3cae528fbee9a2a4
,
0xb1cce69b6aa9ad9a
,
0x044393bb632d94fb
},
&
fe
{
0xc66ef6efeeb5c7e8
,
0x9824c289dd72bb55
,
0x71b1a4d2f119981d
,
0x104fc1aafb0919cc
,
0x0e49df01d942a628
,
0x096c3a09773272d4
},
&
fe
{
0x9abc11eb5fadeff4
,
0x32dca50a885728f0
,
0xfb1fa3721569734c
,
0xc4b76271ea6506b3
,
0xd466a75599ce728e
,
0x0c81d4645f4cb6ed
},
&
fe
{
0x4199f10e5b8be45b
,
0xda64e495b1e87930
,
0xcb353efe9b33e4ff
,
0x9e9efb24aa6424c6
,
0xf08d33680a237465
,
0x0d3378023e4c7406
},
&
fe
{
0x7eb4ae92ec74d3a5
,
0xc341b4aa9fac3497
,
0x5be603899e907687
,
0x03bfd9cca75cbdeb
,
0x564c2935a96bfa93
,
0x0ef3c33371e2fdb5
},
&
fe
{
0x7ee91fd449f6ac2e
,
0xe5d5bd5cb9357a30
,
0x773a8ca5196b1380
,
0xd0fda172174ed023
,
0x6cb95e0fa776aead
,
0x0d22d5a40cec7cff
},
&
fe
{
0xf727e09285fd8519
,
0xdc9d55a83017897b
,
0x7549d8bd057894ae
,
0x178419613d90d8f8
,
0xfce95ebdeb5b490a
,
0x0467ffaef23fc49e
},
&
fe
{
0xc1769e6a7c385f1b
,
0x79bc930deac01c03
,
0x5461c75a23ede3b5
,
0x6e20829e5c230c45
,
0x828e0f1e772a53cd
,
0x116aefa749127bff
},
&
fe
{
0x101c10bf2744c10a
,
0xbbf18d053a6a3154
,
0xa0ecf39ef026f602
,
0xfc009d4996dc5153
,
0xb9000209d5bd08d3
,
0x189e5fe4470cd73c
},
&
fe
{
0x7ebd546ca1575ed2
,
0xe47d5a981d081b55
,
0x57b2b625b6d4ca21
,
0xb0a1ba04228520cc
,
0x98738983c2107ff3
,
0x13dddbc4799d81d6
},
&
fe
{
0x09319f2e39834935
,
0x039e952cbdb05c21
,
0x55ba77a9a2f76493
,
0xfd04e3dfc6086467
,
0xfb95832e7d78742e
,
0x0ef9c24eccaf5e0e
},
&
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
},
}
var
isogenyConstantsG2
=
[
4
][
4
]
*
fe2
{
[
4
]
*
fe2
{
&
fe2
{
fe
{
0x47f671c71ce05e62
,
0x06dd57071206393e
,
0x7c80cd2af3fd71a2
,
0x048103ea9e6cd062
,
0xc54516acc8d037f6
,
0x13808f550920ea41
},
fe
{
0x47f671c71ce05e62
,
0x06dd57071206393e
,
0x7c80cd2af3fd71a2
,
0x048103ea9e6cd062
,
0xc54516acc8d037f6
,
0x13808f550920ea41
},
},
&
fe2
{
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
fe
{
0x5fe55555554c71d0
,
0x873fffdd236aaaa3
,
0x6a6b4619b26ef918
,
0x21c2888408874945
,
0x2836cda7028cabc5
,
0x0ac73310a7fd5abd
},
},
&
fe2
{
fe
{
0x0a0c5555555971c3
,
0xdb0c00101f9eaaae
,
0xb1fb2f941d797997
,
0xd3960742ef416e1c
,
0xb70040e2c20556f4
,
0x149d7861e581393b
},
fe
{
0xaff2aaaaaaa638e8
,
0x439fffee91b55551
,
0xb535a30cd9377c8c
,
0x90e144420443a4a2
,
0x941b66d3814655e2
,
0x0563998853fead5e
},
},
&
fe2
{
fe
{
0x40aac71c71c725ed
,
0x190955557a84e38e
,
0xd817050a8f41abc3
,
0xd86485d4c87f6fb1
,
0x696eb479f885d059
,
0x198e1a74328002d2
},
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
},
},
[
4
]
*
fe2
{
&
fe2
{
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
fe
{
0x1f3affffff13ab97
,
0xf25bfc611da3ff3e
,
0xca3757cb3819b208
,
0x3e6427366f8cec18
,
0x03977bc86095b089
,
0x04f69db13f39a952
},
},
&
fe2
{
fe
{
0x447600000027552e
,
0xdcb8009a43480020
,
0x6f7ee9ce4a6e8b59
,
0xb10330b7c0a95bc6
,
0x6140b1fcfb1e54b7
,
0x0381be097f0bb4e1
},
fe
{
0x7588ffffffd8557d
,
0x41f3ff646e0bffdf
,
0xf7b1e8d2ac426aca
,
0xb3741acd32dbb6f8
,
0xe9daf5b9482d581f
,
0x167f53e0ba7431b8
},
},
&
fe2
{
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
},
&
fe2
{
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
},
},
[
4
]
*
fe2
{
&
fe2
{
fe
{
0x96d8f684bdfc77be
,
0xb530e4f43b66d0e2
,
0x184a88ff379652fd
,
0x57cb23ecfae804e1
,
0x0fd2e39eada3eba9
,
0x08c8055e31c5d5c3
},
fe
{
0x96d8f684bdfc77be
,
0xb530e4f43b66d0e2
,
0x184a88ff379652fd
,
0x57cb23ecfae804e1
,
0x0fd2e39eada3eba9
,
0x08c8055e31c5d5c3
},
},
&
fe2
{
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
fe
{
0xbf0a71c71c91b406
,
0x4d6d55d28b7638fd
,
0x9d82f98e5f205aee
,
0xa27aa27b1d1a18d5
,
0x02c3b2b2d2938e86
,
0x0c7d13420b09807f
},
},
&
fe2
{
fe
{
0xd7f9555555531c74
,
0x21cffff748daaaa8
,
0x5a9ad1866c9bbe46
,
0x4870a2210221d251
,
0x4a0db369c0a32af1
,
0x02b1ccc429ff56af
},
fe
{
0xe205aaaaaaac8e37
,
0xfcdc000768795556
,
0x0c96011a8a1537dd
,
0x1c06a963f163406e
,
0x010df44c82a881e6
,
0x174f45260f808feb
},
},
&
fe2
{
fe
{
0xa470bda12f67f35c
,
0xc0fe38e23327b425
,
0xc9d3d0f2c6f0678d
,
0x1c55c9935b5a982e
,
0x27f6c0e2f0746764
,
0x117c5e6e28aa9054
},
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
},
},
[
4
]
*
fe2
{
&
fe2
{
fe
{
0x0162fffffa765adf
,
0x8f7bea480083fb75
,
0x561b3c2259e93611
,
0x11e19fc1a9c875d5
,
0xca713efc00367660
,
0x03c6a03d41da1151
},
fe
{
0x0162fffffa765adf
,
0x8f7bea480083fb75
,
0x561b3c2259e93611
,
0x11e19fc1a9c875d5
,
0xca713efc00367660
,
0x03c6a03d41da1151
},
},
&
fe2
{
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
fe
{
0x5db0fffffd3b02c5
,
0xd713f52358ebfdba
,
0x5ea60761a84d161a
,
0xbb2c75a34ea6c44a
,
0x0ac6735921c1119b
,
0x0ee3d913bdacfbf6
},
},
&
fe2
{
fe
{
0x66b10000003affc5
,
0xcb1400e764ec0030
,
0xa73e5eb56fa5d106
,
0x8984c913a0fe09a9
,
0x11e10afb78ad7f13
,
0x05429d0e3e918f52
},
fe
{
0x534dffffffc4aae6
,
0x5397ff174c67ffcf
,
0xbff273eb870b251d
,
0xdaf2827152870915
,
0x393a9cbaca9e2dc3
,
0x14be74dbfaee5748
},
},
&
fe2
{
fe
{
0x760900000002fffd
,
0xebf4000bc40c0002
,
0x5f48985753c758ba
,
0x77ce585370525745
,
0x5c071a97a256ec6d
,
0x15f65ec3fa80e493
},
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
},
},
}
minigeth/crypto/bls12381/pairing.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
type
pair
struct
{
g1
*
PointG1
g2
*
PointG2
}
func
newPair
(
g1
*
PointG1
,
g2
*
PointG2
)
pair
{
return
pair
{
g1
,
g2
}
}
// Engine is BLS12-381 elliptic curve pairing engine
type
Engine
struct
{
G1
*
G1
G2
*
G2
fp12
*
fp12
fp2
*
fp2
pairingEngineTemp
pairs
[]
pair
}
// NewPairingEngine creates new pairing engine instance.
func
NewPairingEngine
()
*
Engine
{
fp2
:=
newFp2
()
fp6
:=
newFp6
(
fp2
)
fp12
:=
newFp12
(
fp6
)
g1
:=
NewG1
()
g2
:=
newG2
(
fp2
)
return
&
Engine
{
fp2
:
fp2
,
fp12
:
fp12
,
G1
:
g1
,
G2
:
g2
,
pairingEngineTemp
:
newEngineTemp
(),
}
}
type
pairingEngineTemp
struct
{
t2
[
10
]
*
fe2
t12
[
9
]
fe12
}
func
newEngineTemp
()
pairingEngineTemp
{
t2
:=
[
10
]
*
fe2
{}
for
i
:=
0
;
i
<
10
;
i
++
{
t2
[
i
]
=
&
fe2
{}
}
t12
:=
[
9
]
fe12
{}
return
pairingEngineTemp
{
t2
,
t12
}
}
// AddPair adds a g1, g2 point pair to pairing engine
func
(
e
*
Engine
)
AddPair
(
g1
*
PointG1
,
g2
*
PointG2
)
*
Engine
{
p
:=
newPair
(
g1
,
g2
)
if
!
e
.
isZero
(
p
)
{
e
.
affine
(
p
)
e
.
pairs
=
append
(
e
.
pairs
,
p
)
}
return
e
}
// AddPairInv adds a G1, G2 point pair to pairing engine. G1 point is negated.
func
(
e
*
Engine
)
AddPairInv
(
g1
*
PointG1
,
g2
*
PointG2
)
*
Engine
{
e
.
G1
.
Neg
(
g1
,
g1
)
e
.
AddPair
(
g1
,
g2
)
return
e
}
// Reset deletes added pairs.
func
(
e
*
Engine
)
Reset
()
*
Engine
{
e
.
pairs
=
[]
pair
{}
return
e
}
func
(
e
*
Engine
)
isZero
(
p
pair
)
bool
{
return
e
.
G1
.
IsZero
(
p
.
g1
)
||
e
.
G2
.
IsZero
(
p
.
g2
)
}
func
(
e
*
Engine
)
affine
(
p
pair
)
{
e
.
G1
.
Affine
(
p
.
g1
)
e
.
G2
.
Affine
(
p
.
g2
)
}
func
(
e
*
Engine
)
doublingStep
(
coeff
*
[
3
]
fe2
,
r
*
PointG2
)
{
// Adaptation of Formula 3 in https://eprint.iacr.org/2010/526.pdf
fp2
:=
e
.
fp2
t
:=
e
.
t2
fp2
.
mul
(
t
[
0
],
&
r
[
0
],
&
r
[
1
])
fp2
.
mulByFq
(
t
[
0
],
t
[
0
],
twoInv
)
fp2
.
square
(
t
[
1
],
&
r
[
1
])
fp2
.
square
(
t
[
2
],
&
r
[
2
])
fp2
.
double
(
t
[
7
],
t
[
2
])
fp2
.
add
(
t
[
7
],
t
[
7
],
t
[
2
])
fp2
.
mulByB
(
t
[
3
],
t
[
7
])
fp2
.
double
(
t
[
4
],
t
[
3
])
fp2
.
add
(
t
[
4
],
t
[
4
],
t
[
3
])
fp2
.
add
(
t
[
5
],
t
[
1
],
t
[
4
])
fp2
.
mulByFq
(
t
[
5
],
t
[
5
],
twoInv
)
fp2
.
add
(
t
[
6
],
&
r
[
1
],
&
r
[
2
])
fp2
.
square
(
t
[
6
],
t
[
6
])
fp2
.
add
(
t
[
7
],
t
[
2
],
t
[
1
])
fp2
.
sub
(
t
[
6
],
t
[
6
],
t
[
7
])
fp2
.
sub
(
&
coeff
[
0
],
t
[
3
],
t
[
1
])
fp2
.
square
(
t
[
7
],
&
r
[
0
])
fp2
.
sub
(
t
[
4
],
t
[
1
],
t
[
4
])
fp2
.
mul
(
&
r
[
0
],
t
[
4
],
t
[
0
])
fp2
.
square
(
t
[
2
],
t
[
3
])
fp2
.
double
(
t
[
3
],
t
[
2
])
fp2
.
add
(
t
[
3
],
t
[
3
],
t
[
2
])
fp2
.
square
(
t
[
5
],
t
[
5
])
fp2
.
sub
(
&
r
[
1
],
t
[
5
],
t
[
3
])
fp2
.
mul
(
&
r
[
2
],
t
[
1
],
t
[
6
])
fp2
.
double
(
t
[
0
],
t
[
7
])
fp2
.
add
(
&
coeff
[
1
],
t
[
0
],
t
[
7
])
fp2
.
neg
(
&
coeff
[
2
],
t
[
6
])
}
func
(
e
*
Engine
)
additionStep
(
coeff
*
[
3
]
fe2
,
r
,
q
*
PointG2
)
{
// Algorithm 12 in https://eprint.iacr.org/2010/526.pdf
fp2
:=
e
.
fp2
t
:=
e
.
t2
fp2
.
mul
(
t
[
0
],
&
q
[
1
],
&
r
[
2
])
fp2
.
neg
(
t
[
0
],
t
[
0
])
fp2
.
add
(
t
[
0
],
t
[
0
],
&
r
[
1
])
fp2
.
mul
(
t
[
1
],
&
q
[
0
],
&
r
[
2
])
fp2
.
neg
(
t
[
1
],
t
[
1
])
fp2
.
add
(
t
[
1
],
t
[
1
],
&
r
[
0
])
fp2
.
square
(
t
[
2
],
t
[
0
])
fp2
.
square
(
t
[
3
],
t
[
1
])
fp2
.
mul
(
t
[
4
],
t
[
1
],
t
[
3
])
fp2
.
mul
(
t
[
2
],
&
r
[
2
],
t
[
2
])
fp2
.
mul
(
t
[
3
],
&
r
[
0
],
t
[
3
])
fp2
.
double
(
t
[
5
],
t
[
3
])
fp2
.
sub
(
t
[
5
],
t
[
4
],
t
[
5
])
fp2
.
add
(
t
[
5
],
t
[
5
],
t
[
2
])
fp2
.
mul
(
&
r
[
0
],
t
[
1
],
t
[
5
])
fp2
.
sub
(
t
[
2
],
t
[
3
],
t
[
5
])
fp2
.
mul
(
t
[
2
],
t
[
2
],
t
[
0
])
fp2
.
mul
(
t
[
3
],
&
r
[
1
],
t
[
4
])
fp2
.
sub
(
&
r
[
1
],
t
[
2
],
t
[
3
])
fp2
.
mul
(
&
r
[
2
],
&
r
[
2
],
t
[
4
])
fp2
.
mul
(
t
[
2
],
t
[
1
],
&
q
[
1
])
fp2
.
mul
(
t
[
3
],
t
[
0
],
&
q
[
0
])
fp2
.
sub
(
&
coeff
[
0
],
t
[
3
],
t
[
2
])
fp2
.
neg
(
&
coeff
[
1
],
t
[
0
])
coeff
[
2
]
.
set
(
t
[
1
])
}
func
(
e
*
Engine
)
preCompute
(
ellCoeffs
*
[
68
][
3
]
fe2
,
twistPoint
*
PointG2
)
{
// Algorithm 5 in https://eprint.iacr.org/2019/077.pdf
if
e
.
G2
.
IsZero
(
twistPoint
)
{
return
}
r
:=
new
(
PointG2
)
.
Set
(
twistPoint
)
j
:=
0
for
i
:=
x
.
BitLen
()
-
2
;
i
>=
0
;
i
--
{
e
.
doublingStep
(
&
ellCoeffs
[
j
],
r
)
if
x
.
Bit
(
i
)
!=
0
{
j
++
ellCoeffs
[
j
]
=
fe6
{}
e
.
additionStep
(
&
ellCoeffs
[
j
],
r
,
twistPoint
)
}
j
++
}
}
func
(
e
*
Engine
)
millerLoop
(
f
*
fe12
)
{
pairs
:=
e
.
pairs
ellCoeffs
:=
make
([][
68
][
3
]
fe2
,
len
(
pairs
))
for
i
:=
0
;
i
<
len
(
pairs
);
i
++
{
e
.
preCompute
(
&
ellCoeffs
[
i
],
pairs
[
i
]
.
g2
)
}
fp12
,
fp2
:=
e
.
fp12
,
e
.
fp2
t
:=
e
.
t2
f
.
one
()
j
:=
0
for
i
:=
62
;
/* x.BitLen() - 2 */
i
>=
0
;
i
--
{
if
i
!=
62
{
fp12
.
square
(
f
,
f
)
}
for
i
:=
0
;
i
<=
len
(
pairs
)
-
1
;
i
++
{
fp2
.
mulByFq
(
t
[
0
],
&
ellCoeffs
[
i
][
j
][
2
],
&
pairs
[
i
]
.
g1
[
1
])
fp2
.
mulByFq
(
t
[
1
],
&
ellCoeffs
[
i
][
j
][
1
],
&
pairs
[
i
]
.
g1
[
0
])
fp12
.
mulBy014Assign
(
f
,
&
ellCoeffs
[
i
][
j
][
0
],
t
[
1
],
t
[
0
])
}
if
x
.
Bit
(
i
)
!=
0
{
j
++
for
i
:=
0
;
i
<=
len
(
pairs
)
-
1
;
i
++
{
fp2
.
mulByFq
(
t
[
0
],
&
ellCoeffs
[
i
][
j
][
2
],
&
pairs
[
i
]
.
g1
[
1
])
fp2
.
mulByFq
(
t
[
1
],
&
ellCoeffs
[
i
][
j
][
1
],
&
pairs
[
i
]
.
g1
[
0
])
fp12
.
mulBy014Assign
(
f
,
&
ellCoeffs
[
i
][
j
][
0
],
t
[
1
],
t
[
0
])
}
}
j
++
}
fp12
.
conjugate
(
f
,
f
)
}
func
(
e
*
Engine
)
exp
(
c
,
a
*
fe12
)
{
fp12
:=
e
.
fp12
fp12
.
cyclotomicExp
(
c
,
a
,
x
)
fp12
.
conjugate
(
c
,
c
)
}
func
(
e
*
Engine
)
finalExp
(
f
*
fe12
)
{
fp12
:=
e
.
fp12
t
:=
e
.
t12
// easy part
fp12
.
frobeniusMap
(
&
t
[
0
],
f
,
6
)
fp12
.
inverse
(
&
t
[
1
],
f
)
fp12
.
mul
(
&
t
[
2
],
&
t
[
0
],
&
t
[
1
])
t
[
1
]
.
set
(
&
t
[
2
])
fp12
.
frobeniusMapAssign
(
&
t
[
2
],
2
)
fp12
.
mulAssign
(
&
t
[
2
],
&
t
[
1
])
fp12
.
cyclotomicSquare
(
&
t
[
1
],
&
t
[
2
])
fp12
.
conjugate
(
&
t
[
1
],
&
t
[
1
])
// hard part
e
.
exp
(
&
t
[
3
],
&
t
[
2
])
fp12
.
cyclotomicSquare
(
&
t
[
4
],
&
t
[
3
])
fp12
.
mul
(
&
t
[
5
],
&
t
[
1
],
&
t
[
3
])
e
.
exp
(
&
t
[
1
],
&
t
[
5
])
e
.
exp
(
&
t
[
0
],
&
t
[
1
])
e
.
exp
(
&
t
[
6
],
&
t
[
0
])
fp12
.
mulAssign
(
&
t
[
6
],
&
t
[
4
])
e
.
exp
(
&
t
[
4
],
&
t
[
6
])
fp12
.
conjugate
(
&
t
[
5
],
&
t
[
5
])
fp12
.
mulAssign
(
&
t
[
4
],
&
t
[
5
])
fp12
.
mulAssign
(
&
t
[
4
],
&
t
[
2
])
fp12
.
conjugate
(
&
t
[
5
],
&
t
[
2
])
fp12
.
mulAssign
(
&
t
[
1
],
&
t
[
2
])
fp12
.
frobeniusMapAssign
(
&
t
[
1
],
3
)
fp12
.
mulAssign
(
&
t
[
6
],
&
t
[
5
])
fp12
.
frobeniusMapAssign
(
&
t
[
6
],
1
)
fp12
.
mulAssign
(
&
t
[
3
],
&
t
[
0
])
fp12
.
frobeniusMapAssign
(
&
t
[
3
],
2
)
fp12
.
mulAssign
(
&
t
[
3
],
&
t
[
1
])
fp12
.
mulAssign
(
&
t
[
3
],
&
t
[
6
])
fp12
.
mul
(
f
,
&
t
[
3
],
&
t
[
4
])
}
func
(
e
*
Engine
)
calculate
()
*
fe12
{
f
:=
e
.
fp12
.
one
()
if
len
(
e
.
pairs
)
==
0
{
return
f
}
e
.
millerLoop
(
f
)
e
.
finalExp
(
f
)
return
f
}
// Check computes pairing and checks if result is equal to one
func
(
e
*
Engine
)
Check
()
bool
{
return
e
.
calculate
()
.
isOne
()
}
// Result computes pairing and returns target group element as result.
func
(
e
*
Engine
)
Result
()
*
E
{
r
:=
e
.
calculate
()
e
.
Reset
()
return
r
}
// GT returns target group instance.
func
(
e
*
Engine
)
GT
()
*
GT
{
return
NewGT
()
}
minigeth/crypto/bls12381/swu.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
// swuMapG1 is implementation of Simplified Shallue-van de Woestijne-Ulas Method
// follows the implmentation at draft-irtf-cfrg-hash-to-curve-06.
func
swuMapG1
(
u
*
fe
)
(
*
fe
,
*
fe
)
{
var
params
=
swuParamsForG1
var
tv
[
4
]
*
fe
for
i
:=
0
;
i
<
4
;
i
++
{
tv
[
i
]
=
new
(
fe
)
}
square
(
tv
[
0
],
u
)
mul
(
tv
[
0
],
tv
[
0
],
params
.
z
)
square
(
tv
[
1
],
tv
[
0
])
x1
:=
new
(
fe
)
add
(
x1
,
tv
[
0
],
tv
[
1
])
inverse
(
x1
,
x1
)
e1
:=
x1
.
isZero
()
one
:=
new
(
fe
)
.
one
()
add
(
x1
,
x1
,
one
)
if
e1
{
x1
.
set
(
params
.
zInv
)
}
mul
(
x1
,
x1
,
params
.
minusBOverA
)
gx1
:=
new
(
fe
)
square
(
gx1
,
x1
)
add
(
gx1
,
gx1
,
params
.
a
)
mul
(
gx1
,
gx1
,
x1
)
add
(
gx1
,
gx1
,
params
.
b
)
x2
:=
new
(
fe
)
mul
(
x2
,
tv
[
0
],
x1
)
mul
(
tv
[
1
],
tv
[
0
],
tv
[
1
])
gx2
:=
new
(
fe
)
mul
(
gx2
,
gx1
,
tv
[
1
])
e2
:=
!
isQuadraticNonResidue
(
gx1
)
x
,
y2
:=
new
(
fe
),
new
(
fe
)
if
e2
{
x
.
set
(
x1
)
y2
.
set
(
gx1
)
}
else
{
x
.
set
(
x2
)
y2
.
set
(
gx2
)
}
y
:=
new
(
fe
)
sqrt
(
y
,
y2
)
if
y
.
sign
()
!=
u
.
sign
()
{
neg
(
y
,
y
)
}
return
x
,
y
}
// swuMapG2 is implementation of Simplified Shallue-van de Woestijne-Ulas Method
// defined at draft-irtf-cfrg-hash-to-curve-06.
func
swuMapG2
(
e
*
fp2
,
u
*
fe2
)
(
*
fe2
,
*
fe2
)
{
if
e
==
nil
{
e
=
newFp2
()
}
params
:=
swuParamsForG2
var
tv
[
4
]
*
fe2
for
i
:=
0
;
i
<
4
;
i
++
{
tv
[
i
]
=
e
.
new
()
}
e
.
square
(
tv
[
0
],
u
)
e
.
mul
(
tv
[
0
],
tv
[
0
],
params
.
z
)
e
.
square
(
tv
[
1
],
tv
[
0
])
x1
:=
e
.
new
()
e
.
add
(
x1
,
tv
[
0
],
tv
[
1
])
e
.
inverse
(
x1
,
x1
)
e1
:=
x1
.
isZero
()
e
.
add
(
x1
,
x1
,
e
.
one
())
if
e1
{
x1
.
set
(
params
.
zInv
)
}
e
.
mul
(
x1
,
x1
,
params
.
minusBOverA
)
gx1
:=
e
.
new
()
e
.
square
(
gx1
,
x1
)
e
.
add
(
gx1
,
gx1
,
params
.
a
)
e
.
mul
(
gx1
,
gx1
,
x1
)
e
.
add
(
gx1
,
gx1
,
params
.
b
)
x2
:=
e
.
new
()
e
.
mul
(
x2
,
tv
[
0
],
x1
)
e
.
mul
(
tv
[
1
],
tv
[
0
],
tv
[
1
])
gx2
:=
e
.
new
()
e
.
mul
(
gx2
,
gx1
,
tv
[
1
])
e2
:=
!
e
.
isQuadraticNonResidue
(
gx1
)
x
,
y2
:=
e
.
new
(),
e
.
new
()
if
e2
{
x
.
set
(
x1
)
y2
.
set
(
gx1
)
}
else
{
x
.
set
(
x2
)
y2
.
set
(
gx2
)
}
y
:=
e
.
new
()
e
.
sqrt
(
y
,
y2
)
if
y
.
sign
()
!=
u
.
sign
()
{
e
.
neg
(
y
,
y
)
}
return
x
,
y
}
var
swuParamsForG1
=
struct
{
z
*
fe
zInv
*
fe
a
*
fe
b
*
fe
minusBOverA
*
fe
}{
a
:
&
fe
{
0x2f65aa0e9af5aa51
,
0x86464c2d1e8416c3
,
0xb85ce591b7bd31e2
,
0x27e11c91b5f24e7c
,
0x28376eda6bfc1835
,
0x155455c3e5071d85
},
b
:
&
fe
{
0xfb996971fe22a1e0
,
0x9aa93eb35b742d6f
,
0x8c476013de99c5c4
,
0x873e27c3a221e571
,
0xca72b5e45a52d888
,
0x06824061418a386b
},
z
:
&
fe
{
0x886c00000023ffdc
,
0x0f70008d3090001d
,
0x77672417ed5828c3
,
0x9dac23e943dc1740
,
0x50553f1b9c131521
,
0x078c712fbe0ab6e8
},
zInv
:
&
fe
{
0x0e8a2e8ba2e83e10
,
0x5b28ba2ca4d745d1
,
0x678cd5473847377a
,
0x4c506dd8a8076116
,
0x9bcb227d79284139
,
0x0e8d3154b0ba099a
},
minusBOverA
:
&
fe
{
0x052583c93555a7fe
,
0x3b40d72430f93c82
,
0x1b75faa0105ec983
,
0x2527e7dc63851767
,
0x99fffd1f34fc181d
,
0x097cab54770ca0d3
},
}
var
swuParamsForG2
=
struct
{
z
*
fe2
zInv
*
fe2
a
*
fe2
b
*
fe2
minusBOverA
*
fe2
}{
a
:
&
fe2
{
fe
{
0
,
0
,
0
,
0
,
0
,
0
},
fe
{
0xe53a000003135242
,
0x01080c0fdef80285
,
0xe7889edbe340f6bd
,
0x0b51375126310601
,
0x02d6985717c744ab
,
0x1220b4e979ea5467
},
},
b
:
&
fe2
{
fe
{
0x22ea00000cf89db2
,
0x6ec832df71380aa4
,
0x6e1b94403db5a66e
,
0x75bf3c53a79473ba
,
0x3dd3a569412c0a34
,
0x125cdb5e74dc4fd1
},
fe
{
0x22ea00000cf89db2
,
0x6ec832df71380aa4
,
0x6e1b94403db5a66e
,
0x75bf3c53a79473ba
,
0x3dd3a569412c0a34
,
0x125cdb5e74dc4fd1
},
},
z
:
&
fe2
{
fe
{
0x87ebfffffff9555c
,
0x656fffe5da8ffffa
,
0x0fd0749345d33ad2
,
0xd951e663066576f4
,
0xde291a3d41e980d3
,
0x0815664c7dfe040d
},
fe
{
0x43f5fffffffcaaae
,
0x32b7fff2ed47fffd
,
0x07e83a49a2e99d69
,
0xeca8f3318332bb7a
,
0xef148d1ea0f4c069
,
0x040ab3263eff0206
},
},
zInv
:
&
fe2
{
fe
{
0xacd0000000011110
,
0x9dd9999dc88ccccd
,
0xb5ca2ac9b76352bf
,
0xf1b574bcf4bc90ce
,
0x42dab41f28a77081
,
0x132fc6ac14cd1e12
},
fe
{
0xe396ffffffff2223
,
0x4fbf332fcd0d9998
,
0x0c4bbd3c1aff4cc4
,
0x6b9c91267926ca58
,
0x29ae4da6aef7f496
,
0x10692e942f195791
},
},
minusBOverA
:
&
fe2
{
fe
{
0x903c555555474fb3
,
0x5f98cc95ce451105
,
0x9f8e582eefe0fade
,
0xc68946b6aebbd062
,
0x467a4ad10ee6de53
,
0x0e7146f483e23a05
},
fe
{
0x29c2aaaaaab85af8
,
0xbf133368e30eeefa
,
0xc7a27a7206cffb45
,
0x9dee04ce44c9425c
,
0x04a15ce53464ce83
,
0x0b8fcaf5b59dac95
},
},
}
minigeth/crypto/bls12381/utils.go
0 → 100644
View file @
cc3de083
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bls12381
import
(
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
)
func
bigFromHex
(
hex
string
)
*
big
.
Int
{
return
new
(
big
.
Int
)
.
SetBytes
(
common
.
FromHex
(
hex
))
}
// decodeFieldElement expects 64 byte input with zero top 16 bytes,
// returns lower 48 bytes.
func
decodeFieldElement
(
in
[]
byte
)
([]
byte
,
error
)
{
if
len
(
in
)
!=
64
{
return
nil
,
errors
.
New
(
"invalid field element length"
)
}
// check top bytes
for
i
:=
0
;
i
<
16
;
i
++
{
if
in
[
i
]
!=
byte
(
0x00
)
{
return
nil
,
errors
.
New
(
"invalid field element top bytes"
)
}
}
out
:=
make
([]
byte
,
48
)
copy
(
out
[
:
],
in
[
16
:
])
return
out
,
nil
}
minigeth/crypto/bn256/.bn256_slow.go.swp
deleted
100644 → 0
View file @
f193a1b2
File deleted
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment