You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
6.9 KiB

package gocircomprover
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"strconv"
"strings"
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
)
// ProvingKeyString is the equivalent to the ProvingKey struct in string representation
type ProvingKeyString struct {
A [][]string `json:"A"`
B2 [][][]string `json:"B2"`
B1 [][]string `json:"B1"`
C [][]string `json:"C"`
NVars int `json:"nVars"`
NPublic int `json:"nPublic"`
VkAlpha1 []string `json:"vk_alfa_1"`
VkDelta1 []string `json:"vk_delta_1"`
VkBeta1 []string `json:"vk_beta_1"`
VkBeta2 [][]string `json:"vk_beta_2"`
VkDelta2 [][]string `json:"vk_delta_2"`
HExps [][]string `json:"hExps"`
DomainSize int `json:"domainSize"`
PolsA []map[string]string `json:"polsA"`
PolsB []map[string]string `json:"polsB"`
PolsC []map[string]string `json:"polsC"`
}
// WitnessString contains the Witness in string representation
type WitnessString []string
// ParseWitness parses the json []byte data into the Witness struct
func ParseWitness(wJson []byte) (Witness, error) {
var ws WitnessString
err := json.Unmarshal(wJson, &ws)
if err != nil {
return nil, err
}
var w Witness
for i := 0; i < len(ws); i++ {
bi, err := stringToBigInt(ws[i])
if err != nil {
return nil, err
}
w = append(w, bi)
}
return w, nil
}
// ParseProvingKey parses the json []byte data into the ProvingKey struct
func ParseProvingKey(pkJson []byte) (*ProvingKey, error) {
var pkStr ProvingKeyString
err := json.Unmarshal(pkJson, &pkStr)
if err != nil {
return nil, err
}
pk, err := provingKeyStringToProvingKey(pkStr)
return pk, err
}
func provingKeyStringToProvingKey(ps ProvingKeyString) (*ProvingKey, error) {
var p ProvingKey
var err error
p.A, err = arrayStringToG1(ps.A)
if err != nil {
return nil, err
}
p.B2, err = arrayStringToG2(ps.B2)
if err != nil {
return nil, err
}
p.B1, err = arrayStringToG1(ps.B1)
if err != nil {
return nil, err
}
p.C, err = arrayStringToG1(ps.C)
if err != nil {
return nil, err
}
p.NVars = ps.NVars
p.NPublic = ps.NPublic
p.VkAlpha1, err = stringToG1(ps.VkAlpha1)
if err != nil {
return nil, err
}
p.VkDelta1, err = stringToG1(ps.VkDelta1)
if err != nil {
return nil, err
}
p.VkBeta1, err = stringToG1(ps.VkBeta1)
if err != nil {
return nil, err
}
p.VkBeta2, err = stringToG2(ps.VkBeta2)
if err != nil {
return nil, err
}
p.VkDelta2, err = stringToG2(ps.VkDelta2)
if err != nil {
return nil, err
}
p.HExps, err = arrayStringToG1(ps.HExps)
if err != nil {
return nil, err
}
p.DomainSize = ps.DomainSize
p.PolsA, err = polsStringToBigInt(ps.PolsA)
if err != nil {
return nil, err
}
p.PolsB, err = polsStringToBigInt(ps.PolsB)
if err != nil {
return nil, err
}
p.PolsC, err = polsStringToBigInt(ps.PolsC)
if err != nil {
return nil, err
}
return &p, nil
}
// polsStringToBigInt is for taking string polynomials and converting it to *big.Int polynomials
func polsStringToBigInt(s []map[string]string) ([]map[int]*big.Int, error) {
var o []map[int]*big.Int
for i := 0; i < len(s); i++ {
// var oi map[int]*big.Int
oi := make(map[int]*big.Int)
for j, v := range s[i] {
si, err := stringToBigInt(v)
if err != nil {
return o, err
}
// oi = append(oi, si)
jInt, err := strconv.Atoi(j)
if err != nil {
fmt.Println(j)
return o, err
}
fmt.Println(jInt, si)
oi[jInt] = si
}
o = append(o, oi)
}
return o, nil
}
func arrayStringToBigInt(s []string) ([]*big.Int, error) {
var o []*big.Int
for i := 0; i < len(s); i++ {
si, err := stringToBigInt(s[i])
if err != nil {
return o, nil
}
o = append(o, si)
}
return o, nil
}
func stringToBigInt(s string) (*big.Int, error) {
base := 10
if bytes.HasPrefix([]byte(s), []byte("0x")) {
base = 16
s = strings.TrimPrefix(s, "0x")
}
n, ok := new(big.Int).SetString(s, base)
if !ok {
return nil, fmt.Errorf("Can not parse string to *big.Int: %s", s)
}
return n, nil
}
func addZPadding(b []byte) []byte {
var z [32]byte
var r []byte
r = append(r, z[len(b):]...) // add padding on the left
r = append(r, b...)
return r[:32]
}
func stringToBytes(s string) ([]byte, error) {
if s == "1" {
s = "0"
}
bi, ok := new(big.Int).SetString(s, 10)
if !ok {
return nil, fmt.Errorf("error parsing bigint stringToBytes")
}
b := bi.Bytes()
if len(b) != 32 {
b = addZPadding(b)
}
return b, nil
}
func arrayStringToG1(h [][]string) ([]*bn256.G1, error) {
var o []*bn256.G1
for i := 0; i < len(h); i++ {
hi, err := stringToG1(h[i])
if err != nil {
return o, err
}
o = append(o, hi)
}
return o, nil
}
func arrayStringToG2(h [][][]string) ([]*bn256.G2, error) {
var o []*bn256.G2
for i := 0; i < len(h); i++ {
hi, err := stringToG2(h[i])
if err != nil {
return o, err
}
o = append(o, hi)
}
return o, nil
}
func stringToG1(h []string) (*bn256.G1, error) {
if len(h) <= 2 {
return nil, fmt.Errorf("not enought data for stringToG1")
}
h = h[:2]
hexa := false
if len(h[0]) > 1 {
if "0x" == h[0][:2] {
hexa = true
}
}
in := ""
var b []byte
var err error
if hexa {
for i := range h {
in += strings.TrimPrefix(h[i], "0x")
}
b, err = hex.DecodeString(in)
if err != nil {
return nil, err
}
} else {
// TODO TMP
// TODO use stringToBytes()
if h[0] == "1" {
h[0] = "0"
}
if h[1] == "1" {
h[1] = "0"
}
bi0, ok := new(big.Int).SetString(h[0], 10)
if !ok {
return nil, fmt.Errorf("error parsing stringToG1")
}
bi1, ok := new(big.Int).SetString(h[1], 10)
if !ok {
return nil, fmt.Errorf("error parsing stringToG1")
}
b0 := bi0.Bytes()
b1 := bi1.Bytes()
if len(b0) != 32 {
b0 = addZPadding(b0)
}
if len(b1) != 32 {
b1 = addZPadding(b1)
}
b = append(b, b0...)
b = append(b, b1...)
}
p := new(bn256.G1)
_, err = p.Unmarshal(b)
return p, err
}
func stringToG2(h [][]string) (*bn256.G2, error) {
if len(h) <= 2 {
return nil, fmt.Errorf("not enought data for stringToG2")
}
h = h[:2]
hexa := false
if len(h[0][0]) > 1 {
if "0x" == h[0][0][:2] {
hexa = true
}
}
in := ""
var b []byte
var err error
if hexa {
for i := 0; i < len(h); i++ {
for j := 0; j < len(h[i]); j++ {
in += strings.TrimPrefix(h[i][j], "0x")
}
}
b, err = hex.DecodeString(in)
if err != nil {
return nil, err
}
} else {
// TODO TMP
bH, err := stringToBytes(h[0][1])
if err != nil {
return nil, err
}
b = append(b, bH...)
bH, err = stringToBytes(h[0][0])
if err != nil {
return nil, err
}
b = append(b, bH...)
bH, err = stringToBytes(h[1][1])
if err != nil {
return nil, err
}
b = append(b, bH...)
bH, err = stringToBytes(h[1][0])
if err != nil {
return nil, err
}
b = append(b, bH...)
}
p := new(bn256.G2)
_, err = p.Unmarshal(b)
return p, err
}