|
@ -3,6 +3,7 @@ package parsers |
|
|
import ( |
|
|
import ( |
|
|
"bufio" |
|
|
"bufio" |
|
|
"bytes" |
|
|
"bytes" |
|
|
|
|
|
"encoding/binary" |
|
|
"encoding/hex" |
|
|
"encoding/hex" |
|
|
"encoding/json" |
|
|
"encoding/json" |
|
|
"fmt" |
|
|
"fmt" |
|
@ -599,3 +600,368 @@ func swapEndianness(b []byte) []byte { |
|
|
} |
|
|
} |
|
|
return o |
|
|
return o |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func readNBytes(r io.Reader, n int) ([]byte, error) { |
|
|
|
|
|
b := make([]byte, n) |
|
|
|
|
|
_, err := io.ReadFull(r, b) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return b, err |
|
|
|
|
|
} |
|
|
|
|
|
return b, nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ParsePkBin parses binary file representation of the ProvingKey into the ProvingKey struct
|
|
|
|
|
|
func ParsePkBin(f *os.File) (*types.Pk, error) { |
|
|
|
|
|
o := 0 |
|
|
|
|
|
var pk types.Pk |
|
|
|
|
|
r := bufio.NewReader(f) |
|
|
|
|
|
|
|
|
|
|
|
b, err := readNBytes(r, 12) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.NVars = int(binary.LittleEndian.Uint32(b[:4])) |
|
|
|
|
|
pk.NPublic = int(binary.LittleEndian.Uint32(b[4:8])) |
|
|
|
|
|
pk.DomainSize = int(binary.LittleEndian.Uint32(b[8:12])) |
|
|
|
|
|
o += 12 |
|
|
|
|
|
|
|
|
|
|
|
b, err = readNBytes(r, 8) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pPolsA := int(binary.LittleEndian.Uint32(b[:4])) |
|
|
|
|
|
pPolsB := int(binary.LittleEndian.Uint32(b[4:8])) |
|
|
|
|
|
o += 8 |
|
|
|
|
|
|
|
|
|
|
|
b, err = readNBytes(r, 20) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pPointsA := int(binary.LittleEndian.Uint32(b[:4])) |
|
|
|
|
|
pPointsB1 := int(binary.LittleEndian.Uint32(b[4:8])) |
|
|
|
|
|
pPointsB2 := int(binary.LittleEndian.Uint32(b[8:12])) |
|
|
|
|
|
pPointsC := int(binary.LittleEndian.Uint32(b[12:16])) |
|
|
|
|
|
pPointsHExps := int(binary.LittleEndian.Uint32(b[16:20])) |
|
|
|
|
|
o += 20 |
|
|
|
|
|
|
|
|
|
|
|
b, err = readNBytes(r, 64) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.VkAlpha1 = new(bn256.G1) |
|
|
|
|
|
_, err = pk.VkAlpha1.Unmarshal(fromMont1Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
b, err = readNBytes(r, 64) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.VkBeta1 = new(bn256.G1) |
|
|
|
|
|
_, err = pk.VkBeta1.Unmarshal(fromMont1Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
b, err = readNBytes(r, 64) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.VkDelta1 = new(bn256.G1) |
|
|
|
|
|
_, err = pk.VkDelta1.Unmarshal(fromMont1Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
b, err = readNBytes(r, 128) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.VkBeta2 = new(bn256.G2) |
|
|
|
|
|
_, err = pk.VkBeta2.Unmarshal(fromMont2Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
b, err = readNBytes(r, 128) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.VkDelta2 = new(bn256.G2) |
|
|
|
|
|
_, err = pk.VkDelta2.Unmarshal(fromMont2Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
o += 448 |
|
|
|
|
|
if o != pPolsA { |
|
|
|
|
|
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPolsA, o) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// PolsA
|
|
|
|
|
|
for i := 0; i < pk.NVars; i++ { |
|
|
|
|
|
b, err = readNBytes(r, 4) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
keysLength := int(binary.LittleEndian.Uint32(b[:4])) |
|
|
|
|
|
o += 4 |
|
|
|
|
|
polsMap := make(map[int]*big.Int) |
|
|
|
|
|
for j := 0; j < keysLength; j++ { |
|
|
|
|
|
bK, err := readNBytes(r, 4) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
key := int(binary.LittleEndian.Uint32(bK[:4])) |
|
|
|
|
|
o += 4 |
|
|
|
|
|
|
|
|
|
|
|
b, err := readNBytes(r, 32) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
polsMap[key] = new(big.Int).SetBytes(fromMont1R(b[:32])) |
|
|
|
|
|
o += 32 |
|
|
|
|
|
} |
|
|
|
|
|
pk.PolsA = append(pk.PolsA, polsMap) |
|
|
|
|
|
} |
|
|
|
|
|
if o != pPolsB { |
|
|
|
|
|
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPolsB, o) |
|
|
|
|
|
} |
|
|
|
|
|
// PolsB
|
|
|
|
|
|
for i := 0; i < pk.NVars; i++ { |
|
|
|
|
|
b, err = readNBytes(r, 4) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
keysLength := int(binary.LittleEndian.Uint32(b[:4])) |
|
|
|
|
|
o += 4 |
|
|
|
|
|
polsMap := make(map[int]*big.Int) |
|
|
|
|
|
for j := 0; j < keysLength; j++ { |
|
|
|
|
|
bK, err := readNBytes(r, 4) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
key := int(binary.LittleEndian.Uint32(bK[:4])) |
|
|
|
|
|
o += 4 |
|
|
|
|
|
|
|
|
|
|
|
b, err := readNBytes(r, 32) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
polsMap[key] = new(big.Int).SetBytes(fromMont1R(b[:32])) |
|
|
|
|
|
o += 32 |
|
|
|
|
|
} |
|
|
|
|
|
pk.PolsB = append(pk.PolsB, polsMap) |
|
|
|
|
|
} |
|
|
|
|
|
if o != pPointsA { |
|
|
|
|
|
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsA, o) |
|
|
|
|
|
} |
|
|
|
|
|
// A
|
|
|
|
|
|
for i := 0; i < pk.NVars; i++ { |
|
|
|
|
|
b, err = readNBytes(r, 64) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
p1 := new(bn256.G1) |
|
|
|
|
|
_, err = p1.Unmarshal(fromMont1Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.A = append(pk.A, p1) |
|
|
|
|
|
o += 64 |
|
|
|
|
|
} |
|
|
|
|
|
if o != pPointsB1 { |
|
|
|
|
|
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsB1, o) |
|
|
|
|
|
} |
|
|
|
|
|
// B1
|
|
|
|
|
|
for i := 0; i < pk.NVars; i++ { |
|
|
|
|
|
b, err = readNBytes(r, 64) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
p1 := new(bn256.G1) |
|
|
|
|
|
_, err = p1.Unmarshal(fromMont1Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.B1 = append(pk.B1, p1) |
|
|
|
|
|
o += 64 |
|
|
|
|
|
} |
|
|
|
|
|
if o != pPointsB2 { |
|
|
|
|
|
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsB2, o) |
|
|
|
|
|
} |
|
|
|
|
|
// B2
|
|
|
|
|
|
for i := 0; i < pk.NVars; i++ { |
|
|
|
|
|
b, err = readNBytes(r, 128) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
p2 := new(bn256.G2) |
|
|
|
|
|
_, err = p2.Unmarshal(fromMont2Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.B2 = append(pk.B2, p2) |
|
|
|
|
|
o += 128 |
|
|
|
|
|
} |
|
|
|
|
|
if o != pPointsC { |
|
|
|
|
|
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsC, o) |
|
|
|
|
|
} |
|
|
|
|
|
// C
|
|
|
|
|
|
zb := make([]byte, 64) |
|
|
|
|
|
z := new(bn256.G1) |
|
|
|
|
|
_, err = z.Unmarshal(zb) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.C = append(pk.C, z) // circom behaviour (3x null==["0", "0", "0"])
|
|
|
|
|
|
pk.C = append(pk.C, z) |
|
|
|
|
|
pk.C = append(pk.C, z) |
|
|
|
|
|
for i := pk.NPublic + 1; i < pk.NVars; i++ { |
|
|
|
|
|
b, err = readNBytes(r, 64) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
p1 := new(bn256.G1) |
|
|
|
|
|
_, err = p1.Unmarshal(fromMont1Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.C = append(pk.C, p1) |
|
|
|
|
|
o += 64 |
|
|
|
|
|
} |
|
|
|
|
|
if o != pPointsHExps { |
|
|
|
|
|
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsHExps, o) |
|
|
|
|
|
} |
|
|
|
|
|
for i := 0; i < pk.DomainSize; i++ { |
|
|
|
|
|
b, err = readNBytes(r, 64) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
p1 := new(bn256.G1) |
|
|
|
|
|
_, err = p1.Unmarshal(fromMont1Q(b)) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, err |
|
|
|
|
|
} |
|
|
|
|
|
pk.HExps = append(pk.HExps, p1) |
|
|
|
|
|
} |
|
|
|
|
|
return &pk, nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func fromMont1Q(m []byte) []byte { |
|
|
|
|
|
a := new(big.Int).SetBytes(swapEndianness(m[:32])) |
|
|
|
|
|
b := new(big.Int).SetBytes(swapEndianness(m[32:64])) |
|
|
|
|
|
|
|
|
|
|
|
x := coordFromMont(a, types.Q) |
|
|
|
|
|
y := coordFromMont(b, types.Q) |
|
|
|
|
|
if bytes.Equal(x.Bytes(), big.NewInt(1).Bytes()) { |
|
|
|
|
|
x = big.NewInt(0) |
|
|
|
|
|
} |
|
|
|
|
|
if bytes.Equal(y.Bytes(), big.NewInt(1).Bytes()) { |
|
|
|
|
|
y = big.NewInt(0) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
xBytes := x.Bytes() |
|
|
|
|
|
yBytes := y.Bytes() |
|
|
|
|
|
if len(xBytes) != 32 { |
|
|
|
|
|
xBytes = addZPadding(xBytes) |
|
|
|
|
|
} |
|
|
|
|
|
if len(yBytes) != 32 { |
|
|
|
|
|
yBytes = addZPadding(yBytes) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var p []byte |
|
|
|
|
|
p = append(p, xBytes...) |
|
|
|
|
|
p = append(p, yBytes...) |
|
|
|
|
|
|
|
|
|
|
|
return p |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func fromMont2Q(m []byte) []byte { |
|
|
|
|
|
a := new(big.Int).SetBytes(swapEndianness(m[:32])) |
|
|
|
|
|
b := new(big.Int).SetBytes(swapEndianness(m[32:64])) |
|
|
|
|
|
c := new(big.Int).SetBytes(swapEndianness(m[64:96])) |
|
|
|
|
|
d := new(big.Int).SetBytes(swapEndianness(m[96:128])) |
|
|
|
|
|
|
|
|
|
|
|
x := coordFromMont(a, types.Q) |
|
|
|
|
|
y := coordFromMont(b, types.Q) |
|
|
|
|
|
z := coordFromMont(c, types.Q) |
|
|
|
|
|
t := coordFromMont(d, types.Q) |
|
|
|
|
|
|
|
|
|
|
|
if bytes.Equal(x.Bytes(), big.NewInt(1).Bytes()) { |
|
|
|
|
|
x = big.NewInt(0) |
|
|
|
|
|
} |
|
|
|
|
|
if bytes.Equal(y.Bytes(), big.NewInt(1).Bytes()) { |
|
|
|
|
|
y = big.NewInt(0) |
|
|
|
|
|
} |
|
|
|
|
|
if bytes.Equal(z.Bytes(), big.NewInt(1).Bytes()) { |
|
|
|
|
|
z = big.NewInt(0) |
|
|
|
|
|
} |
|
|
|
|
|
if bytes.Equal(t.Bytes(), big.NewInt(1).Bytes()) { |
|
|
|
|
|
t = big.NewInt(0) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
xBytes := x.Bytes() |
|
|
|
|
|
yBytes := y.Bytes() |
|
|
|
|
|
zBytes := z.Bytes() |
|
|
|
|
|
tBytes := t.Bytes() |
|
|
|
|
|
if len(xBytes) != 32 { |
|
|
|
|
|
xBytes = addZPadding(xBytes) |
|
|
|
|
|
} |
|
|
|
|
|
if len(yBytes) != 32 { |
|
|
|
|
|
yBytes = addZPadding(yBytes) |
|
|
|
|
|
} |
|
|
|
|
|
if len(zBytes) != 32 { |
|
|
|
|
|
zBytes = addZPadding(zBytes) |
|
|
|
|
|
} |
|
|
|
|
|
if len(tBytes) != 32 { |
|
|
|
|
|
tBytes = addZPadding(tBytes) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var p []byte |
|
|
|
|
|
p = append(p, yBytes...) // swap
|
|
|
|
|
|
p = append(p, xBytes...) |
|
|
|
|
|
p = append(p, tBytes...) |
|
|
|
|
|
p = append(p, zBytes...) |
|
|
|
|
|
|
|
|
|
|
|
return p |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func fromMont1R(m []byte) []byte { |
|
|
|
|
|
a := new(big.Int).SetBytes(swapEndianness(m[:32])) |
|
|
|
|
|
|
|
|
|
|
|
x := coordFromMont(a, types.R) |
|
|
|
|
|
|
|
|
|
|
|
return x.Bytes() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func fromMont2R(m []byte) []byte { |
|
|
|
|
|
a := new(big.Int).SetBytes(swapEndianness(m[:32])) |
|
|
|
|
|
b := new(big.Int).SetBytes(swapEndianness(m[32:64])) |
|
|
|
|
|
c := new(big.Int).SetBytes(swapEndianness(m[64:96])) |
|
|
|
|
|
d := new(big.Int).SetBytes(swapEndianness(m[96:128])) |
|
|
|
|
|
|
|
|
|
|
|
x := coordFromMont(a, types.R) |
|
|
|
|
|
y := coordFromMont(b, types.R) |
|
|
|
|
|
z := coordFromMont(c, types.R) |
|
|
|
|
|
t := coordFromMont(d, types.R) |
|
|
|
|
|
|
|
|
|
|
|
var p []byte |
|
|
|
|
|
p = append(p, y.Bytes()...) // swap
|
|
|
|
|
|
p = append(p, x.Bytes()...) |
|
|
|
|
|
p = append(p, t.Bytes()...) |
|
|
|
|
|
p = append(p, z.Bytes()...) |
|
|
|
|
|
|
|
|
|
|
|
return p |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func coordFromMont(u, q *big.Int) *big.Int { |
|
|
|
|
|
return new(big.Int).Mod( |
|
|
|
|
|
new(big.Int).Mul( |
|
|
|
|
|
u, |
|
|
|
|
|
new(big.Int).ModInverse( |
|
|
|
|
|
new(big.Int).Lsh(big.NewInt(1), 256), |
|
|
|
|
|
q, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
q, |
|
|
|
|
|
) |
|
|
|
|
|
} |