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.

341 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(append(randomness, byte(round)))
  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 length < %d",
  154. MinRandomnessLen)
  155. }
  156. // set tau from randomness
  157. tw := tau(round, randomness)
  158. newSRS := computeContribution(tw, prevSRS)
  159. proof := genProof(tw, prevSRS, newSRS)
  160. return newSRS, proof, nil
  161. }
  162. func checkG1PointCorrectness(p *bls12381.PointG1) error {
  163. // i) non-empty
  164. if p == nil {
  165. return fmt.Errorf("empty point value")
  166. }
  167. // ii) non-zero
  168. if g1.IsZero(p) {
  169. return fmt.Errorf("point can not be zero")
  170. }
  171. // iii) in the correct prime order of subgroups
  172. if !g1.IsOnCurve(p) {
  173. return fmt.Errorf("point not on curve")
  174. }
  175. if !g1.InCorrectSubgroup(p) {
  176. return fmt.Errorf("point not in the correct prime order of subgroups")
  177. }
  178. return nil
  179. }
  180. func checkG2PointCorrectness(p *bls12381.PointG2) error {
  181. // i) non-empty
  182. if p == nil {
  183. return fmt.Errorf("empty point value")
  184. }
  185. // ii) non-zero
  186. if g2.IsZero(p) {
  187. return fmt.Errorf("point can not be zero")
  188. }
  189. // iii) in the correct prime order of subgroups
  190. if !g2.IsOnCurve(p) {
  191. return fmt.Errorf("point not on curve")
  192. }
  193. if !g2.InCorrectSubgroup(p) {
  194. return fmt.Errorf("point not in the correct prime order of subgroups")
  195. }
  196. return nil
  197. }
  198. // VerifyNewSRSFromPrevSRS checks the correct computation of the new SRS
  199. // respectively from the previous SRS. These are the checks that the Sequencer
  200. // would do.
  201. func VerifyNewSRSFromPrevSRS(prevSRS, newSRS *SRS, proof *Proof) bool {
  202. pairing := bls12381.NewEngine()
  203. // 1. check that elements of the newSRS are valid points
  204. for i := 0; i < len(newSRS.G1Powers); i++ {
  205. if err := checkG1PointCorrectness(newSRS.G1Powers[i]); err != nil {
  206. return false
  207. }
  208. }
  209. for i := 0; i < len(newSRS.G2Powers); i++ {
  210. if err := checkG2PointCorrectness(newSRS.G2Powers[i]); err != nil {
  211. return false
  212. }
  213. }
  214. // 2. check proof.G1PTau == newSRS.G1Powers[1]
  215. if !g1.Equal(proof.G1PTau, newSRS.G1Powers[1]) {
  216. return false
  217. }
  218. // 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ)
  219. // e([τ]₁, [p]₂) == e([τ']₁, [1]₂)
  220. eL := pairing.AddPair(prevSRS.G1Powers[1], proof.G2P).Result()
  221. eR := pairing.AddPair(newSRS.G1Powers[1], g2.One()).Result()
  222. if !eL.Equal(eR) {
  223. return false
  224. }
  225. // 4. check newSRS following the powers of tau structure
  226. for i := 0; i < len(newSRS.G1Powers)-1; i++ {
  227. // i) e([τ'ⁱ]₁, [τ']₂) == e([τ'ⁱ⁺¹]₁, [1]₂), for i ∈ [1, n−1]
  228. eL := pairing.AddPair(newSRS.G1Powers[i], newSRS.G2Powers[1]).Result()
  229. eR := pairing.AddPair(newSRS.G1Powers[i+1], g2.One()).Result()
  230. if !eL.Equal(eR) {
  231. return false
  232. }
  233. }
  234. for i := 0; i < len(newSRS.G2Powers)-1; i++ {
  235. // ii) e([τ']₁, [τ'ʲ]₂) == e([1]₁, [τ'ʲ⁺¹]₂), for j ∈ [1, m−1]
  236. eL := pairing.AddPair(newSRS.G1Powers[1], newSRS.G2Powers[i]).Result()
  237. eR := pairing.AddPair(g1.One(), newSRS.G2Powers[i+1]).Result()
  238. if !eL.Equal(eR) {
  239. return false
  240. }
  241. }
  242. return true
  243. }
  244. // VerifyState acts similarly to VerifyNewSRSFromPrevSRS, but verifying the
  245. // given State (which can be obtained from the Sequencer)
  246. func VerifyState(s *State) bool {
  247. pairing := bls12381.NewEngine()
  248. for _, t := range s.Transcripts {
  249. // 1. check that elements of the SRS are valid points
  250. for i := 0; i < len(t.PowersOfTau.G1Powers); i++ {
  251. if err := checkG1PointCorrectness(t.PowersOfTau.G1Powers[i]); err != nil {
  252. return false
  253. }
  254. }
  255. for i := 0; i < len(t.PowersOfTau.G2Powers); i++ {
  256. if err := checkG2PointCorrectness(t.PowersOfTau.G2Powers[i]); err != nil {
  257. return false
  258. }
  259. }
  260. // 2. check t.Witness.RunningProducts[last] == t.PowersOfTau.G1Powers[1]
  261. if !g1.Equal(t.Witness.RunningProducts[len(t.Witness.RunningProducts)-1],
  262. t.PowersOfTau.G1Powers[1]) {
  263. return false
  264. }
  265. // 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ)
  266. // e([τ]₁, [p]₂) == e([τ']₁, [1]₂)
  267. eL := pairing.AddPair(t.Witness.RunningProducts[len(t.Witness.RunningProducts)-2], t.Witness.PotPubKeys[len(t.Witness.PotPubKeys)-1]).Result()
  268. eR := pairing.AddPair(t.Witness.RunningProducts[len(t.Witness.RunningProducts)-1], g2.One()).Result()
  269. if !eL.Equal(eR) {
  270. return false
  271. }
  272. // 4. check newSRS following the powers of tau structure
  273. for i := 0; i < len(t.PowersOfTau.G1Powers)-1; i++ {
  274. // i) e([τ'ⁱ]₁, [τ']₂) == e([τ'ⁱ⁺¹]₁, [1]₂), for i ∈ [1, n−1]
  275. eL := pairing.AddPair(t.PowersOfTau.G1Powers[i], t.PowersOfTau.G2Powers[1]).Result()
  276. eR := pairing.AddPair(t.PowersOfTau.G1Powers[i+1], g2.One()).Result()
  277. if !eL.Equal(eR) {
  278. return false
  279. }
  280. }
  281. for i := 0; i < len(t.PowersOfTau.G2Powers)-1; i++ {
  282. // ii) e([τ']₁, [τ'ʲ]₂) == e([1]₁, [τ'ʲ⁺¹]₂), for j ∈ [1, m−1]
  283. eL := pairing.AddPair(t.PowersOfTau.G1Powers[1], t.PowersOfTau.G2Powers[i]).Result()
  284. eR := pairing.AddPair(g1.One(), t.PowersOfTau.G2Powers[i+1]).Result()
  285. if !eL.Equal(eR) {
  286. return false
  287. }
  288. }
  289. }
  290. return true
  291. }