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.
 
 

268 lines
8.1 KiB

package kzgceremony
import (
"encoding/hex"
"encoding/json"
"fmt"
"strings"
bls12381 "github.com/kilic/bls12-381"
)
// UnmarshalJSON implements the State json unmarshaler, compatible
// with the official Ethereum KZG Ceremony formats
func (s *State) UnmarshalJSON(b []byte) error {
var sStr stateStr
if err := json.Unmarshal(b, &sStr); err != nil {
return err
}
var err error
s.ParticipantIDs = sStr.ParticipantIDs
s.ParticipantECDSASignatures = sStr.ParticipantECDSASignatures
s.Transcripts = make([]Transcript, len(sStr.Transcripts))
for i := 0; i < len(sStr.Transcripts); i++ {
if sStr.Transcripts[i].NumG1Powers != uint64(len(sStr.Transcripts[i].PowersOfTau.G1Powers)) {
return fmt.Errorf("wrong NumG1Powers")
}
if sStr.Transcripts[i].NumG2Powers != uint64(len(sStr.Transcripts[i].PowersOfTau.G2Powers)) {
return fmt.Errorf("wrong NumG2Powers")
}
s.Transcripts[i].NumG1Powers = sStr.Transcripts[i].NumG1Powers
s.Transcripts[i].NumG2Powers = sStr.Transcripts[i].NumG2Powers
s.Transcripts[i].PowersOfTau = &SRS{}
s.Transcripts[i].PowersOfTau.G1Powers, err =
stringsToPointsG1(sStr.Transcripts[i].PowersOfTau.G1Powers)
if err != nil {
return err
}
s.Transcripts[i].PowersOfTau.G2Powers, err =
stringsToPointsG2(sStr.Transcripts[i].PowersOfTau.G2Powers)
if err != nil {
return err
}
s.Transcripts[i].Witness = &Witness{}
s.Transcripts[i].Witness.RunningProducts, err =
stringsToPointsG1(sStr.Transcripts[i].Witness.RunningProducts)
if err != nil {
return err
}
s.Transcripts[i].Witness.PotPubKeys, err =
stringsToPointsG2(sStr.Transcripts[i].Witness.PotPubKeys)
if err != nil {
return err
}
s.Transcripts[i].Witness.BLSSignatures, err =
stringsToPointsG1(sStr.Transcripts[i].Witness.BLSSignatures)
if err != nil {
return err
}
}
return err
}
// MarshalJSON implements the State json marshaler, compatible with the
// official Ethereum KZG Ceremony formats
func (s State) MarshalJSON() ([]byte, error) {
var sStr stateStr
sStr.ParticipantIDs = s.ParticipantIDs
sStr.ParticipantECDSASignatures = s.ParticipantECDSASignatures
sStr.Transcripts = make([]transcriptStr, len(s.Transcripts))
for i := 0; i < len(s.Transcripts); i++ {
if s.Transcripts[i].NumG1Powers != uint64(len(s.Transcripts[i].PowersOfTau.G1Powers)) {
return nil, fmt.Errorf("wrong NumG1Powers")
}
if s.Transcripts[i].NumG2Powers != uint64(len(s.Transcripts[i].PowersOfTau.G2Powers)) {
return nil, fmt.Errorf("wrong NumG2Powers")
}
sStr.Transcripts[i].NumG1Powers = s.Transcripts[i].NumG1Powers
sStr.Transcripts[i].NumG2Powers = s.Transcripts[i].NumG2Powers
sStr.Transcripts[i].PowersOfTau = powersOfTauStr{}
sStr.Transcripts[i].PowersOfTau.G1Powers =
g1PointsToStrings(s.Transcripts[i].PowersOfTau.G1Powers)
sStr.Transcripts[i].PowersOfTau.G2Powers =
g2PointsToStrings(s.Transcripts[i].PowersOfTau.G2Powers)
sStr.Transcripts[i].Witness = witnessStr{}
sStr.Transcripts[i].Witness.RunningProducts =
g1PointsToStrings(s.Transcripts[i].Witness.RunningProducts)
sStr.Transcripts[i].Witness.PotPubKeys =
g2PointsToStrings(s.Transcripts[i].Witness.PotPubKeys)
sStr.Transcripts[i].Witness.BLSSignatures =
g1PointsToStrings(s.Transcripts[i].Witness.BLSSignatures)
}
return json.Marshal(sStr)
}
// UnmarshalJSON implements the BatchContribution json unmarshaler, compatible
// with the official Ethereum KZG Ceremony formats
func (c *BatchContribution) UnmarshalJSON(b []byte) error {
var cStr batchContributionStr
if err := json.Unmarshal(b, &cStr); err != nil {
return err
}
var err error
c.Contributions = make([]Contribution, len(cStr.Contributions))
for i := 0; i < len(cStr.Contributions); i++ {
c.Contributions[i].NumG1Powers = cStr.Contributions[i].NumG1Powers
c.Contributions[i].NumG2Powers = cStr.Contributions[i].NumG2Powers
c.Contributions[i].PowersOfTau = &SRS{}
c.Contributions[i].PowersOfTau.G1Powers, err =
stringsToPointsG1(cStr.Contributions[i].PowersOfTau.G1Powers)
if err != nil {
return err
}
c.Contributions[i].PowersOfTau.G2Powers, err =
stringsToPointsG2(cStr.Contributions[i].PowersOfTau.G2Powers)
if err != nil {
return err
}
g2sBytes, err := hex.DecodeString(strings.TrimPrefix(cStr.Contributions[i].PotPubKey, "0x"))
if err != nil {
return err
}
c.Contributions[i].PotPubKey, err = g2.FromCompressed(g2sBytes)
if err != nil {
return err
}
}
return err
}
// MarshalJSON implements the BatchContribution json marshaler, compatible
// with the official Ethereum KZG Ceremony formats
func (c BatchContribution) MarshalJSON() ([]byte, error) {
var cStr batchContributionStr
cStr.Contributions = make([]contributionStr, len(c.Contributions))
for i := 0; i < len(c.Contributions); i++ {
cStr.Contributions[i].NumG1Powers = c.Contributions[i].NumG1Powers
cStr.Contributions[i].NumG2Powers = c.Contributions[i].NumG2Powers
cStr.Contributions[i].PowersOfTau = powersOfTauStr{}
cStr.Contributions[i].PowersOfTau.G1Powers =
g1PointsToStrings(c.Contributions[i].PowersOfTau.G1Powers)
cStr.Contributions[i].PowersOfTau.G2Powers =
g2PointsToStrings(c.Contributions[i].PowersOfTau.G2Powers)
cStr.Contributions[i].PotPubKey = "0x" +
hex.EncodeToString(g2.ToCompressed(c.Contributions[i].PotPubKey))
}
return json.Marshal(cStr)
}
type powersOfTauStr struct {
G1Powers []string `json:"G1Powers"`
G2Powers []string `json:"G2Powers"`
}
type witnessStr struct {
RunningProducts []string `json:"runningProducts"`
PotPubKeys []string `json:"potPubkeys"`
BLSSignatures []string `json:"blsSignatures"`
}
type transcriptStr struct {
NumG1Powers uint64 `json:"numG1Powers"`
NumG2Powers uint64 `json:"numG2Powers"`
PowersOfTau powersOfTauStr `json:"powersOfTau"`
Witness witnessStr `json:"witness"`
}
type contributionStr struct {
NumG1Powers uint64 `json:"numG1Powers"`
NumG2Powers uint64 `json:"numG2Powers"`
PowersOfTau powersOfTauStr `json:"powersOfTau"`
PotPubKey string `json:"potPubkey"`
}
type batchContributionStr struct {
Contributions []contributionStr `json:"contributions"`
}
type stateStr struct {
Transcripts []transcriptStr `json:"transcripts"`
ParticipantIDs []string `json:"participantIds"`
ParticipantECDSASignatures []string `json:"participantEcdsaSignatures"`
}
func g1PointsToStrings(points []*bls12381.PointG1) []string {
n := len(points)
g1s := make([]string, n)
for i := 0; i < n; i++ {
if points[i] == nil {
g1s[i] = ""
continue
}
g1s[i] = "0x" + hex.EncodeToString(g1.ToCompressed(points[i]))
}
return g1s
}
func g2PointsToStrings(points []*bls12381.PointG2) []string {
n := len(points)
g2s := make([]string, n)
for i := 0; i < n; i++ {
if points[i] == nil {
g2s[i] = ""
continue
}
g2s[i] = "0x" + hex.EncodeToString(g2.ToCompressed(points[i]))
}
return g2s
}
// stringsToPointsG1 parses the strings that represent the G1 points in the
// ZCash compressed format into bls12381.PointG1 data structure. Additionally
// it checks the points correctness
func stringsToPointsG1(s []string) ([]*bls12381.PointG1, error) {
n := len(s)
g1s := make([]*bls12381.PointG1, n)
for i := 0; i < n; i++ {
if s[i] == "" {
continue
}
g1sBytes, err := hex.DecodeString(strings.TrimPrefix(s[i], "0x"))
if err != nil {
return nil, err
}
g1s_i, err := g1.FromCompressed(g1sBytes)
if err != nil {
return nil, err
}
if err := checkG1PointCorrectness(g1s_i); err != nil {
return nil, err
}
g1s[i] = g1s_i
}
return g1s, nil
}
// stringsToPointsG2 parses the strings that represent the G2 points in the
// ZCash compressed format into bls12381.PointG2 data structure. Additionally
// it checks the points correctness
func stringsToPointsG2(s []string) ([]*bls12381.PointG2, error) {
n := len(s)
g2s := make([]*bls12381.PointG2, n)
for i := 0; i < n; i++ {
if s[i] == "" {
continue
}
g2sBytes, err := hex.DecodeString(strings.TrimPrefix(s[i], "0x"))
if err != nil {
return nil, err
}
g2s_i, err := g2.FromCompressed(g2sBytes)
if err != nil {
return nil, err
}
if err := checkG2PointCorrectness(g2s_i); err != nil {
return nil, err
}
g2s[i] = g2s_i
}
return g2s, nil
}