templates.bls12_381

  1import smartpy as sp
  2
  3
  4@sp.module
  5def main():
  6    class Bls12_381(sp.Contract):
  7        def __init__(self, g1, g2, fr):
  8            sp.cast(g1, sp.bls12_381_g1)
  9            sp.cast(g2, sp.bls12_381_g2)
 10            sp.cast(fr, sp.bls12_381_fr)
 11            self.data.g1 = g1
 12            self.data.g2 = g2
 13            self.data.fr = fr
 14            self.data.toIntResult = None
 15            self.data.checkResult = None
 16
 17        @sp.entrypoint
 18        def add(self, g1, g2, fr):
 19            """ADD: Add two curve points or field elements.
 20
 21            :: bls12_381_g1 : bls12_381_g1 : 'S -> bls12_381_g1 : 'S
 22            :: bls12_381_g2 : bls12_381_g2 : 'S -> bls12_381_g2 : 'S
 23            :: bls12_381_fr : bls12_381_fr : 'S -> bls12_381_fr : 'S
 24            """
 25            self.data.g1 += g1
 26            self.data.g2 += g2
 27            self.data.fr += fr
 28
 29        @sp.entrypoint
 30        def negate(self):
 31            """NEG: Negate a curve point or field element.
 32
 33            :: bls12_381_g1 : 'S -> bls12_381_g1 : 'S
 34            :: bls12_381_g2 : 'S -> bls12_381_g2 : 'S
 35            :: bls12_381_fr : 'S -> bls12_381_fr : 'S
 36            """
 37            self.data.g1 = -self.data.g1
 38            self.data.g2 = -self.data.g2
 39            self.data.fr = -self.data.fr
 40
 41        @sp.entrypoint
 42        def toInt(self):
 43            """Convert a field (the bls12_381_fr element) to type int.
 44
 45            The returned value is always between 0 (inclusive) and the order of Fr (exclusive).
 46
 47            :: bls12_381_fr : 'S -> int : 'S
 48            """
 49            self.data.toIntResult = sp.Some(sp.to_int(self.data.fr))
 50
 51        @sp.entrypoint
 52        def mul(self, fr, i, n):
 53            """MUL: Multiply a curve point or field element by a scalar field element.
 54
 55            Fr elements can be built from naturals by multiplying by the unit of Fr
 56            using PUSH bls12_381_fr 1; MUL. Note that the multiplication will be
 57            computed using the natural modulo the order of Fr.
 58
 59            :: bls12_381_g1 : bls12_381_fr : 'S -> bls12_381_g1 : 'S
 60            :: bls12_381_g2 : bls12_381_fr : 'S -> bls12_381_g2 : 'S
 61            :: bls12_381_fr : bls12_381_fr : 'S -> bls12_381_fr : 'S
 62            :: nat : bls12_381_fr : 'S -> bls12_381_fr : 'S
 63            :: int : bls12_381_fr : 'S -> bls12_381_fr : 'S
 64            :: bls12_381_fr : nat : 'S -> bls12_381_fr : 'S
 65            :: bls12_381_fr : int : 'S -> bls12_381_fr : 'S
 66            """
 67            sp.cast(fr, sp.bls12_381_fr)
 68            sp.cast(i, sp.int)
 69            sp.cast(n, sp.nat)
 70            self.data.g1 = sp.mul(self.data.g1, fr)
 71            self.data.g2 = sp.mul(self.data.g2, fr)
 72            self.data.fr = sp.mul(self.data.fr, fr)
 73            self.data.fr = sp.mul(self.data.fr, i)
 74            self.data.fr = sp.mul(self.data.fr, n)
 75
 76        @sp.entrypoint
 77        def pairing_check(self, listOfPairs):
 78            """PAIRING_CHECK: Verify that the product of pairings of the given list
 79                of points is equal to 1 in Fq12.
 80
 81                Returns true if the list is empty.
 82                Can be used to verify if two pairings P1 and P2 are equal by verifying
 83                P1 * P2^(-1) = 1.
 84
 85            :: list (pair bls12_381_g1 bls12_381_g2) : 'S -> bool : 'S
 86            """
 87            self.data.checkResult = sp.Some(sp.pairing_check(listOfPairs))
 88
 89        @sp.entrypoint
 90        def conv(self, params):
 91            """Non trivial combined operations
 92
 93            This tests that compiler rewriting doesn't break it.
 94            """
 95            sp.cast(params, sp.mutez)
 96            self.data.fr = sp.mul(
 97                sp.fst(sp.ediv(params, sp.mutez(1)).unwrap_some()),
 98                sp.bls12_381_fr("0x01"),
 99            )
100
101
102@sp.add_test()
103def test():
104    g1 = sp.bls12_381_g1(
105        "0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"
106    )
107    g2 = sp.bls12_381_g2(
108        "0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801"
109    )
110    fr = sp.bls12_381_fr(
111        "0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221"
112    )
113
114    sc = sp.test_scenario("BLS12-381", main)
115    c1 = main.Bls12_381(g1=g1, g2=g2, fr=fr)
116
117    sc += c1
118    sc.h2("Basic maths")
119
120    c1.add(g1=g1, g2=g2, fr=fr)
121
122    sc.verify_equal(sp.add(g1, g1), g1 + g1)
123    sc.verify_equal(sp.add(g2, g2), g2 + g2)
124    sc.verify_equal(sp.add(fr, fr), fr + fr)
125
126    c1.negate()
127    c1.toInt()
128
129    sc.verify(
130        c1.data.toIntResult
131        == sp.Some(
132            22010428307259596184589026230464379215728696454789911939124470486372749680037
133        )
134    )
135
136    c1.mul(fr=fr, i=sp.int(5), n=sp.nat(1))
137
138    sc.verify_equal(
139        c1.data.g1,
140        sp.bls12_381_g1(
141            "0x07e3cf9affb773e08cda3f38f9b2b33f1aa234178c17fe4a234b80ec8622861ffb925c4b49595d7e06b7317d377bb89102b3ca77a64fe03fb281212382950e94ad03303e8cead0bfaab99ec00e4741076d7162a1e6b7e273269fc3e6a1b9f0f1"
142        ),
143    )
144    sc.verify_equal(
145        c1.data.g2,
146        sp.bls12_381_g2(
147            "0x1097f5e2e3bffa9f555ffdc44f556f363bb1b5cee17c95c8c834740843c84bbd7d2072cb91c86e55b78749dba3b8a8400b20d78f6ec32e931d0f6202b2bc31af0f38acc3aad291b2cc15c625f26bdcd8ebd09559e723855a00ce308f3cd28c040512aa4787618c0c79bcf95abd570f3debc94ece2a77ab66f332c7440372ccd3648037ba7e814d555f85498d74b3a42e009613a78c1c6ab3c6adf8c1f9c9b51a1c3399ec736526a98c888cb147eb86e49e22d9703571a096bce1a93d152f405c"
148        ),
149    )
150    sc.verify_equal(
151        c1.data.fr,
152        sp.bls12_381_fr(
153            "0xc1255b074cd1d8fb783ef0b09e62886a82747c03e9dd5f9f3f7b2be9e2054834"
154        ),
155    )
156
157    sc.h2("Pairing check")
158
159    # From https://gitlab.com/metastatedev/tezos/-/commit/f10c39e0030e6b4fdd416a62de7b80b6ffdfeacf
160
161    # The verifying key, proof, and inputs are generated from
162    # ZoKrates, modified to use BLS12-381.
163    # The circuit proves knowledge of a square root of 113569.
164
165    input_x = sp.bls12_381_fr(
166        "0xa1bb010000000000000000000000000000000000000000000000000000000000"
167    )
168    input_y = sp.bls12_381_fr(
169        "0x0100000000000000000000000000000000000000000000000000000000000000"
170    )
171    proof_a = sp.bls12_381_g1(
172        "0x0a2841423326ab08f5f406409775e43fa0f9a0b97631fa85d2dd9242507d25059e9cf48b8b98f99a0008671423a148ec106d70637056972ef49fb6f62de2e89ba3682b9972292b6bb4e6f53799a75d2f8001ccfde280d8ac05fc209352236cbd"
173    )
174    proof_b = sp.bls12_381_g2(
175        "0x0fced939fb1ad733f99669f50a383ef632f6d41dfbde434a6715afd5c7dfbb7bc5835e058ad8b590c7b38dd137d0bd0f0e1540f1b45d8aa626c360e2ea484a116243f7c802034de915db6b18d5303946f676e423cbd6046d37a82208d500625a11c7250ccb953a7ee49d704ad14de4b727733cff7cf06875d8b6444f3c0a8cbf0bd980e539c74bd5b37bb15fe816f23407d269193105fda71adf35fae9309d9d46729fcd4685699097a86f0460a2bc8b16293940cabfdcfe0f27e4107e74e90c"
176    )
177    proof_c = sp.bls12_381_g1(
178        "0x0a1fb5a144ca3bdfe4ad0f183cf71dd7fdd28cbef4fcd47b5b419f65186703f62ecaaa1255fa21a6ebdd917ab1f9bd9707de7066865e2ff3875e22088619125a0d4088a622ab42224425ef89a5a149ce2db9c8292b62c7e7aaa7e87f3535304b"
179    )
180
181    vk_gamma_c = sp.bls12_381_g1(
182        "0x063bd6e11e2fcaac1dd8cf68c6b1925a73c3c583e298ed37c41c3715115cf96358a42dbe85a0228cbfd8a6c8a8c54cd015b5ae2860d1cc47f84698d951f14d9448d03f04df2ca0ffe609a2067d6f1a892163a5e05e541279134cae52b1f23c6b"
183    )
184    vk_gamma_b = sp.bls12_381_g1(
185        "0x11f5b5db1da7f1f26217edcce2219d016003af6e5b4d1ca3ad0ff477e354717e658bf16beddc4f4fb76ce39d3327811e0601709dc7ed98c70463cfa1ba33f99851b52b51d1a042d7425bec6277287441c399973632445ce61e7fdd63a70f0f60"
186    )
187    vk_gamma_a = sp.bls12_381_g1(
188        "0x03535a322edd23c55b0ca025e54d450d95df49cc9ee873dcd500e8219f4771264bf159b3b105954d85c7bea8ffe1ea0400c767fe58989366c2837fba76f1b4f46644f19be8ad01e22d894b649e427e0d7e04677ee3919d982f0f96bb0a2f0c34"
189    )
190    vk_delta = sp.bls12_381_g2(
191        "0x10c6d5cdca84fc3c7f33061add256f48e0ab03a697832b338901898b650419eb6f334b28153fb73ad2ecd1cd2ac67053161e9f46cfbdaf7b1132a4654a55162850249650f9b873ac3113fa8c02ef1cd1df481480a4457f351d28f4da89d19fa405c3d77f686dc9a24d2681c9184bf2b091f62e6b24df651a3da8bd7067e14e7908fb02f8955b84af5081614cb5bc49b416d9edf914fc608c441b3f2eb8b6043736ddb9d4e4d62334a23b5625c14ef3e1a7e99258386310221b22d83a5eac035c"
192    )
193    vk_gamma = sp.bls12_381_g2(
194        "0x16dcbd28bff336c2649c7dd1d8391ac7ce6f7ef0124a9db7a4a485a124199eded7ce963c1c18aee1eca9994fe06f192c00e0fb653e1fc737d8d0e2f2f91424ca01f6e6e7c5c04f1c43db03a2900cf6b942aaed6ae77daea6200e094b78c38d770028d531a9d1a118ec23d5a39be7aa6dc28f778da1988856d2235c4a35e81fa48380f050d4baf7ebd7b5e058bf294da916afc34562f097c02a8fcbcf62a00de44f8ae6cfa7acb8ad254e3aeea8b2af12f65b7ee0f54855cb9bd432f3436f238f"
195    )
196    vk_b = sp.bls12_381_g2(
197        "0x0e9383f98df2c6e8b5b45f3876c3384596a0cdbc41349f83c4380bf463a050cdbd1d5057aa483a642e66486d1ed7362a1869e423c3877095e215c17282b11108601166f928043254bbce603bf86f4cec9f2e97e9660e98e4f5bce9b2b3bbacb40946b702ccfcc9a31e0bfc1543a2128edcc95807740a2310ae25eb47b935648e392c58dfae5b5e899d3b970d64e4e9e209741ea8bfedcfcc16b3fd890ff02c788ec0943feaaf01bbb354317acb85fcfd611133e4e563d53ca4e0f50e21cf2e7e"
198    )
199    vk_a = sp.bls12_381_g1(
200        "0x1040577c7d349e332735fc947c868c24a665f812f5dc1e7f60e65e2df80be2267a4b7341ed2287285fccd517acd96d910abba947235c364553aa6445f2f2b3a1a728225a330286ba5197ab87f0edc560d89fc7b623812f7d0d633341726e597a"
201    )
202
203    vk_x = sc.compute(
204        sp.mul(vk_gamma_b, input_x) + sp.mul(vk_gamma_c, input_y) + vk_gamma_a
205    )
206
207    c1.pairing_check(
208        sp.list(
209            [(proof_a, proof_b), (-vk_x, vk_gamma), (-proof_c, vk_delta), (-vk_a, vk_b)]
210        )
211    )
212
213    sc.verify(c1.data.checkResult == sp.Some(True))
214
215    c1.pairing_check([(g1, g2), (g1, g2)])
216
217    sc.verify(c1.data.checkResult == sp.Some(False))
218
219    c1.pairing_check([])
220
221    sc.verify(c1.data.checkResult == sp.Some(True))
222
223    c1.conv(sp.mutez(5))
224
225    sc.verify_equal(
226        c1.data.fr,
227        sp.bls12_381_fr(
228            "0x0500000000000000000000000000000000000000000000000000000000000000"
229        ),
230    )