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.

281 lines
8.0 KiB

  1. package kzgceremony
  2. import (
  3. "fmt"
  4. "math/big"
  5. bls12381 "github.com/kilic/bls12-381"
  6. )
  7. // MinRandomnessLen is the minimum accepted length for the user defined
  8. // randomness
  9. const MinRandomnessLen = 64
  10. var g1 *bls12381.G1
  11. var g2 *bls12381.G2
  12. func init() {
  13. g1 = bls12381.NewG1()
  14. g2 = bls12381.NewG2()
  15. }
  16. // State represents the data structure obtained from the Sequencer at the
  17. // /info/current_state endpoint
  18. type State struct {
  19. Transcripts []Transcript
  20. ParticipantIDs []string // WIP
  21. ParticipantECDSASignatures []string
  22. }
  23. // BatchContribution represents the data structure obtained from the Sequencer
  24. // at the /contribute endpoint
  25. type BatchContribution struct {
  26. Contributions []Contribution
  27. }
  28. type Contribution struct {
  29. NumG1Powers uint64
  30. NumG2Powers uint64
  31. PowersOfTau *SRS
  32. PotPubKey *bls12381.PointG2
  33. }
  34. type Transcript struct {
  35. NumG1Powers uint64
  36. NumG2Powers uint64
  37. PowersOfTau *SRS
  38. Witness *Witness
  39. }
  40. type Witness struct {
  41. RunningProducts []*bls12381.PointG1
  42. PotPubKeys []*bls12381.PointG2
  43. BLSSignatures []*bls12381.PointG1
  44. }
  45. // SRS contains the powers of tau in G1 & G2, eg.
  46. // [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁,
  47. // [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂
  48. type SRS struct {
  49. G1Powers []*bls12381.PointG1
  50. G2Powers []*bls12381.PointG2
  51. }
  52. type toxicWaste struct {
  53. tau *big.Int
  54. TauG2 *bls12381.PointG2 // Proof.G2P
  55. }
  56. // Proof contains g₂ᵖ and g₂^τ', used by the verifier
  57. type Proof struct {
  58. G2P *bls12381.PointG2 // g₂ᵖ
  59. G1PTau *bls12381.PointG1 // g₂^τ' = g₂^{p ⋅ τ}
  60. }
  61. // Contribute takes the last State and computes a new State using the defined
  62. // randomness
  63. func (cs *State) Contribute(randomness []byte) (*State, error) {
  64. ns := State{}
  65. ns.Transcripts = make([]Transcript, len(cs.Transcripts))
  66. for i := 0; i < len(cs.Transcripts); i++ {
  67. ns.Transcripts[i].NumG1Powers = cs.Transcripts[i].NumG1Powers
  68. ns.Transcripts[i].NumG2Powers = cs.Transcripts[i].NumG2Powers
  69. newSRS, proof, err := Contribute(cs.Transcripts[i].PowersOfTau, randomness)
  70. if err != nil {
  71. return nil, err
  72. }
  73. ns.Transcripts[i].PowersOfTau = newSRS
  74. ns.Transcripts[i].Witness = &Witness{}
  75. ns.Transcripts[i].Witness.RunningProducts =
  76. append(cs.Transcripts[i].Witness.RunningProducts, proof.G1PTau)
  77. ns.Transcripts[i].Witness.PotPubKeys =
  78. append(cs.Transcripts[i].Witness.PotPubKeys, proof.G2P)
  79. ns.Transcripts[i].Witness.BLSSignatures = cs.Transcripts[i].Witness.BLSSignatures
  80. }
  81. ns.ParticipantIDs = cs.ParticipantIDs // TODO add github id (id_token.sub)
  82. ns.ParticipantECDSASignatures = cs.ParticipantECDSASignatures
  83. return &ns, nil
  84. }
  85. // Contribute takes the last BatchContribution and computes a new
  86. // BatchContribution using the defined randomness
  87. func (pb *BatchContribution) Contribute(randomness []byte) (*BatchContribution, error) {
  88. nb := BatchContribution{}
  89. nb.Contributions = make([]Contribution, len(pb.Contributions))
  90. for i := 0; i < len(pb.Contributions); i++ {
  91. nb.Contributions[i].NumG1Powers = pb.Contributions[i].NumG1Powers
  92. nb.Contributions[i].NumG2Powers = pb.Contributions[i].NumG2Powers
  93. newSRS, proof, err := Contribute(pb.Contributions[i].PowersOfTau, randomness)
  94. if err != nil {
  95. return nil, err
  96. }
  97. nb.Contributions[i].PowersOfTau = newSRS
  98. nb.Contributions[i].PotPubKey = proof.G2P
  99. }
  100. return &nb, nil
  101. }
  102. // newEmptySRS creates an empty SRS filled by [1]₁ & [1]₂ points in all
  103. // respective arrays positions
  104. func newEmptySRS(nG1, nG2 int) *SRS {
  105. g1s := make([]*bls12381.PointG1, nG1)
  106. g2s := make([]*bls12381.PointG2, nG2)
  107. for i := 0; i < nG1; i++ {
  108. g1s[i] = g1.One()
  109. }
  110. for i := 0; i < nG2; i++ {
  111. g2s[i] = g2.One()
  112. }
  113. return &SRS{g1s, g2s}
  114. }
  115. func tau(randomness []byte) *toxicWaste {
  116. tau := new(big.Int).Mod(
  117. new(big.Int).SetBytes(randomness),
  118. g2.Q())
  119. tau_Fr := bls12381.NewFr().FromBytes(tau.Bytes())
  120. TauG2 := g2.New()
  121. g2.MulScalar(TauG2, g2.One(), tau_Fr)
  122. return &toxicWaste{tau, TauG2}
  123. }
  124. func computeContribution(t *toxicWaste, prevSRS *SRS) *SRS {
  125. srs := newEmptySRS(len(prevSRS.G1Powers), len(prevSRS.G2Powers))
  126. Q := g1.Q() // Q = |G1| == |G2|
  127. // fmt.Println("Computing [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁, for n =", len(prevSRS.G1s))
  128. for i := 0; i < len(prevSRS.G1Powers); i++ {
  129. tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q)
  130. tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes())
  131. g1.MulScalar(srs.G1Powers[i], prevSRS.G1Powers[i], tau_i_Fr)
  132. }
  133. // fmt.Println("Computing [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂, for n =", len(prevSRS.G2s))
  134. for i := 0; i < len(prevSRS.G2Powers); i++ {
  135. tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q)
  136. tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes())
  137. g2.MulScalar(srs.G2Powers[i], prevSRS.G2Powers[i], tau_i_Fr)
  138. }
  139. return srs
  140. }
  141. func genProof(toxicWaste *toxicWaste, prevSRS, newSRS *SRS) *Proof {
  142. G1_p := g1.New()
  143. tau_Fr := bls12381.NewFr().FromBytes(toxicWaste.tau.Bytes())
  144. g1.MulScalar(G1_p, prevSRS.G1Powers[1], tau_Fr) // g_1^{tau'} = g_1^{p * tau}, where p=toxicWaste.tau
  145. return &Proof{toxicWaste.TauG2, G1_p}
  146. }
  147. // Contribute takes as input the previous SRS and a random
  148. // byte slice, and returns the new SRS together with the Proof
  149. func Contribute(prevSRS *SRS, randomness []byte) (*SRS, *Proof, error) {
  150. if len(randomness) < MinRandomnessLen {
  151. return nil, nil, fmt.Errorf("err randomness") // WIP
  152. }
  153. // set tau from randomness
  154. tw := tau(randomness)
  155. newSRS := computeContribution(tw, prevSRS)
  156. proof := genProof(tw, prevSRS, newSRS)
  157. return newSRS, proof, nil
  158. }
  159. func checkG1PointCorrectness(p *bls12381.PointG1) error {
  160. // i) non-empty
  161. if p == nil {
  162. return fmt.Errorf("empty point value")
  163. }
  164. // ii) non-zero
  165. if g1.IsZero(p) {
  166. return fmt.Errorf("point can not be zero")
  167. }
  168. // iii) in the correct prime order of subgroups
  169. if !g1.IsOnCurve(p) {
  170. return fmt.Errorf("point not on curve")
  171. }
  172. if !g1.InCorrectSubgroup(p) {
  173. return fmt.Errorf("point not in the correct prime order of subgroups")
  174. }
  175. return nil
  176. }
  177. func checkG2PointCorrectness(p *bls12381.PointG2) error {
  178. // i) non-empty
  179. if p == nil {
  180. return fmt.Errorf("empty point value")
  181. }
  182. // ii) non-zero
  183. if g2.IsZero(p) {
  184. return fmt.Errorf("point can not be zero")
  185. }
  186. // iii) in the correct prime order of subgroups
  187. if !g2.IsOnCurve(p) {
  188. return fmt.Errorf("point not on curve")
  189. }
  190. if !g2.InCorrectSubgroup(p) {
  191. return fmt.Errorf("point not in the correct prime order of subgroups")
  192. }
  193. return nil
  194. }
  195. // Verify checks the correct computation of the new SRS respectively from the
  196. // previous SRS
  197. func Verify(prevSRS, newSRS *SRS, proof *Proof) bool {
  198. pairing := bls12381.NewEngine()
  199. // 1. check that elements of the newSRS are valid points
  200. for i := 0; i < len(newSRS.G1Powers); i++ {
  201. if err := checkG1PointCorrectness(newSRS.G1Powers[i]); err != nil {
  202. return false
  203. }
  204. }
  205. for i := 0; i < len(newSRS.G2Powers); i++ {
  206. if err := checkG2PointCorrectness(newSRS.G2Powers[i]); err != nil {
  207. return false
  208. }
  209. }
  210. // 2. check proof.G1PTau == newSRS.G1Powers[1]
  211. if !g1.Equal(proof.G1PTau, newSRS.G1Powers[1]) {
  212. return false
  213. }
  214. // 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ)
  215. // e([τ]₁, [p]₂) == e([τ']₁, [1]₂)
  216. eL := pairing.AddPair(prevSRS.G1Powers[1], proof.G2P).Result()
  217. eR := pairing.AddPair(newSRS.G1Powers[1], g2.One()).Result()
  218. if !eL.Equal(eR) {
  219. return false
  220. }
  221. // 4. check newSRS following the powers of tau structure
  222. for i := 0; i < len(newSRS.G1Powers)-1; i++ {
  223. // i) e([τ'ⁱ]₁, [τ']₂) == e([τ'ⁱ⁺¹]₁, [1]₂), for i ∈ [1, n−1]
  224. eL := pairing.AddPair(newSRS.G1Powers[i], newSRS.G2Powers[1]).Result()
  225. eR := pairing.AddPair(newSRS.G1Powers[i+1], g2.One()).Result()
  226. if !eL.Equal(eR) {
  227. return false
  228. }
  229. }
  230. for i := 0; i < len(newSRS.G2Powers)-1; i++ {
  231. // ii) e([τ']₁, [τ'ʲ]₂) == e([1]₁, [τ'ʲ⁺¹]₂), for j ∈ [1, m−1]
  232. eL := pairing.AddPair(newSRS.G1Powers[1], newSRS.G2Powers[i]).Result()
  233. eR := pairing.AddPair(g1.One(), newSRS.G2Powers[i+1]).Result()
  234. if !eL.Equal(eR) {
  235. return false
  236. }
  237. }
  238. return true
  239. }