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.

340 lines
10 KiB

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