libsrs.ml
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2023 Nomadic Labs <contact@nomadic-labs.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
open Bls12_381
module G1 = G1
module G2 = G2
module G1_carray = Octez_bls12_381_polynomial.G1_carray
module G2_carray = Octez_bls12_381_polynomial.G2_carray
module Checks = struct
let equality (g1_elements : G1_carray.t) (g2_elements : G2_carray.t) =
let g1 = G1_carray.get g1_elements 0 in
let g2 = G2_carray.get g2_elements 0 in
G1_carray.iteri_copy_elt
(fun i g1i ->
let g2i = G2_carray.get g2_elements i in
let gt_element1 = Pairing.pairing g1i g2 in
let gt_element2 = Pairing.pairing g1 g2i in
assert (GT.eq gt_element1 gt_element2))
g1_elements
let incrementation_g1 g1_elements g2_elements =
let g2 = G2_carray.get g2_elements 0 in
let g2x = G2_carray.get g2_elements 1 in
for i = 0 to G1_carray.length g1_elements - 2 do
let g1i = G1_carray.get g1_elements i in
let g1iplus = G1_carray.get g1_elements (i + 1) in
let gt_element1 = Pairing.pairing g1i g2x in
let gt_element2 = Pairing.pairing g1iplus g2 in
assert (GT.eq gt_element1 gt_element2)
done
let incrementation_g2 g1_elements g2_elements =
let g1 = G1_carray.get g1_elements 0 in
let g1x = G1_carray.get g1_elements 1 in
for i = 0 to G2_carray.length g2_elements - 2 do
let g2i = G2_carray.get g2_elements i in
let g2iplus = G2_carray.get g2_elements (i + 1) in
let gt_element1 = Pairing.pairing g1x g2i in
let gt_element2 = Pairing.pairing g1 g2iplus in
assert (GT.eq gt_element1 gt_element2)
done
let pairings g1_elements g2_elements =
equality g1_elements g2_elements ;
incrementation_g1 g1_elements g2_elements ;
incrementation_g2 g1_elements g2_elements
end
let exact_log2 p =
if p <= 0 then raise @@ Invalid_argument (string_of_int p) ;
let rec aux res p =
if p = 1 then res
else
let p' = p lsr 1 in
if p' = 1 then
if p mod 2 <> 0 then raise @@ Invalid_argument "not a power of 2"
else res + 1
else aux (res + 1) p'
in
aux 0 p
(** The binary format of our Srs is a sequence of G1 or G2 elements. *)
module Srs = struct
let to_file gs file to_compressed_bytes iter =
let oc = open_out_bin file in
try
iter (fun g1 -> output_bytes oc (to_compressed_bytes g1)) gs ;
close_out oc
with e ->
close_out oc ;
raise e
let gs1_to_file gs output_file =
to_file gs output_file G1.to_compressed_bytes G1_carray.iter_copy_elt
let gs2_to_file gs output_file =
to_file gs output_file G2.to_compressed_bytes G2_carray.iter_copy_elt
end
(** This module handles the file format of the result of powers-of-tau ceremony.
The layout of the file can be found at the bottom of this file
https://github.com/ebfull/powersoftau/blob/master/src/bin/verify.rs
to be
let tau_powers_length = 1 lsl power in
G1.size_in_bytes (* alpha in g1 *)
+ G1.size_in_bytes (* beta in g1 *)
+ G2.size_in_bytes (* beta in g2 *)
+ (tau_powers_length * G1.size_in_bytes) (* g1_coeffs *)
+ (tau_powers_length * G2.size_in_bytes) (* g2_coeffs *)
+ (tau_powers_length * G1.size_in_bytes) (* g1_alpha_coeffs *)
+ (tau_powers_length * G1.size_in_bytes) (* g1_beta_coeffs *)
+ ((tau_powers_length - 1) * G1.size_in_bytes) (* h *)
*)
module Powers_of_tau = struct
let generate_domain power =
let size = 1 lsl power in
let rec get_omega limit =
if limit < 32 then Fr.square (get_omega (limit + 1))
else
Fr.of_string
"0x16a2a19edfe81f20d09b681922c813b4b63683508c2280b93829971f439f0d2b"
in
let omega = get_omega power in
let rec encoded_pow_x acc xi i =
if i = 0 then List.rev acc
else encoded_pow_x (xi :: acc) (Fr.mul xi omega) (i - 1)
in
Array.of_list @@ encoded_pow_x [] Fr.one size
(* Derives the power that generated the file from the total size of the
file using this formula:
let tau_powers_length = (total - g1 - g2) / (4g1+g2)
let power = log2 tau_powers_length
*)
let power_of_radixfile radixfile =
let ic = open_in_bin radixfile in
try
let g1 = G1.size_in_bytes in
let g2 = G2.size_in_bytes in
let filesize = in_channel_length ic in
close_in ic ;
let nb_elements = (filesize - g1 - g2) / ((4 * g1) + g2) in
exact_log2 nb_elements
with e ->
close_in ic ;
raise e
let to_gs radixfile skip size_in_bytes of_bytes_exn evaluation_ecfft of_array
=
let power = power_of_radixfile radixfile in
let buf = Bytes.create size_in_bytes in
let read ic =
Stdlib.really_input ic buf 0 size_in_bytes ;
of_bytes_exn buf
in
let ic = open_in_bin radixfile in
try
Stdlib.seek_in ic skip ;
let size = 1 lsl power in
let points = Array.init size (fun _i -> read ic) |> of_array in
close_in ic ;
let domain = Octez_bls12_381_polynomial.Domain.build_power_of_two power in
let points = evaluation_ecfft ~domain ~points in
points
with e ->
close_in ic ;
raise e
let to_g1s radixfile =
let skip_header =
(* Skip alpha_g1, beta_g1 and beta_g2 *)
(2 * G1.size_in_bytes) + G2.size_in_bytes
in
to_gs
radixfile
skip_header
G1.size_in_bytes
G1.of_bytes_exn
G1_carray.evaluation_ecfft
G1_carray.of_array
let to_g2s radixfile =
let power = power_of_radixfile radixfile in
let size = 1 lsl power in
let skip_header =
(* Skip alpha_g1, beta_g1 and beta_g2 *)
(2 * G1.size_in_bytes) + G2.size_in_bytes
in
let skip_g2s =
let skip_g1s = size * G1.size_in_bytes in
skip_header + skip_g1s
in
to_gs
radixfile
skip_g2s
G2.size_in_bytes
G2.of_bytes_exn
G2_carray.evaluation_ecfft
G2_carray.of_array
end