ekzg_trusted_setup/lib.rs
1use bls12_381::{G1Point, G2Point};
2use serde::Deserialize;
3use serialization::trusted_setup::{deserialize_g1_points, deserialize_g2_points, SubgroupCheck};
4
5const TRUSTED_SETUP_JSON: &str = include_str!("../data/trusted_setup_4096.json");
6
7/// Represents an Ethereum trusted setup used for KZG commitments on the BLS12-381 curve.
8#[derive(Deserialize, Debug, PartialEq, Eq)]
9pub struct TrustedSetup {
10 /// G1 Monomial represents a list of group elements in the G1 group on the bls12-381 curve.
11 pub g1_monomial: Vec<G1Point>,
12 /// G2 Monomial represents a list of group elements in the G2 group on the bls12-381 curve.
13 pub g2_monomial: Vec<G2Point>,
14}
15
16/// Represents a serialized Ethereum trusted setup used for KZG commitments on the BLS12-381 curve.
17///
18/// This struct holds hex-encoded group elements in G1 and G2, provided in monomial and lagrange bases.
19/// These elements are used to construct commitment and verification keys for polynomial commitment schemes.
20///
21/// The setup is typically loaded from a JSON file matching the format used in Ethereum consensus specifications.
22#[derive(Deserialize, Debug, PartialEq, Eq)]
23struct TrustedSetupJSON {
24 /// G1 Monomial represents a list of uncompressed
25 /// hex encoded group elements in the G1 group on the bls12-381 curve.
26 ///
27 /// Ethereum has multiple trusted setups, however the one being
28 /// used currently contains 4096 G1 elements.
29 pub g1_monomial: Vec<String>,
30 /// G2 Monomial represents a list of uncompressed hex encoded
31 /// group elements in the G2 group on the bls12-381 curve.
32 ///
33 /// The length of this vector is 65.
34 pub g2_monomial: Vec<String>,
35}
36
37impl TrustedSetupJSON {
38 /// Converts the `TrustedSetupJSON` into a `TrustedSetup` with subgroup checks.
39 ///
40 /// Panics if any of the points are not in the correct subgroup
41 fn to_trusted_setup(&self) -> TrustedSetup {
42 let g1_monomial = deserialize_g1_points(&self.g1_monomial, SubgroupCheck::Check);
43 let g2_monomial = deserialize_g2_points(&self.g2_monomial, SubgroupCheck::Check);
44 TrustedSetup {
45 g1_monomial,
46 g2_monomial,
47 }
48 }
49
50 /// Converts the `TrustedSetupJSON` into a `TrustedSetup` without doing subgroup checks.
51 ///
52 /// Panics if:
53 /// - The hex string does not start with 0x
54 /// - The hex string does not represent a valid point in the G1/G2 group
55 fn to_trusted_setup_unchecked(&self) -> TrustedSetup {
56 let g1_monomial = deserialize_g1_points(&self.g1_monomial, SubgroupCheck::NoCheck);
57 let g2_monomial = deserialize_g2_points(&self.g2_monomial, SubgroupCheck::NoCheck);
58 TrustedSetup {
59 g1_monomial,
60 g2_monomial,
61 }
62 }
63
64 /// Parse a JSON string in the format specified by the ethereum trusted setup.
65 ///
66 /// This method does not check that the points are in the correct subgroup.
67 fn from_json_unchecked(json: &str) -> Self {
68 // Note: it is fine to panic here since this method is called on startup
69 // and we want to fail fast if the trusted setup is malformed.
70 serde_json::from_str(json)
71 .expect("could not parse json string into a TrustedSetup structure")
72 }
73
74 /// Loads the official trusted setup file being used on mainnet from the embedded data folder.
75 fn from_embed() -> Self {
76 Self::from_json_unchecked(TRUSTED_SETUP_JSON)
77 }
78}
79
80impl Default for TrustedSetup {
81 fn default() -> Self {
82 let trusted_setup_json = TrustedSetupJSON::from_embed();
83 // We have a test that checks the embedded trusted setup is well-formed.
84 trusted_setup_json.to_trusted_setup_unchecked()
85 }
86}
87
88impl TrustedSetup {
89 /// Parse a Json string in the format specified by the ethereum trusted setup.
90 ///
91 /// The file that is being used on mainnet is located here: https://github.com/ethereum/consensus-specs/blob/389b2ddfb954731da7ccf4c0ef89fab2d4575b99/presets/mainnet/trusted_setups/trusted_setup_4096.json
92 ///
93 // The format that the file follows that this function also accepts, looks like the following:
94 /*
95 {
96 "g1_monomial": [
97 "0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb",
98 ...
99 ],
100 "g1_lagrange": [
101 "0xa0413c0dcafec6dbc9f47d66785cf1e8c981044f7d13cfe3e4fcbb71b5408dfde6312493cb3c1d30516cb3ca88c03654",
102 "0x8b997fb25730d661918371bb41f2a6e899cac23f04fc5365800b75433c0a953250e15e7a98fb5ca5cc56a8cd34c20c57",
103 ...
104 ],
105 "g2_monomial": [
106 "0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8",
107 ...
108 ]
109 }
110 */
111 /// Note: That we do not need the g1_lagrange points so they are skipped.
112 pub fn from_json(json: &str) -> Self {
113 let trusted_setup_json = TrustedSetupJSON::from_json_unchecked(json);
114 trusted_setup_json.to_trusted_setup()
115 }
116
117 /// Parse a Json string in the format specified by the ethereum trusted setup.
118 ///
119 /// This method does not check that the points are in the correct subgroup.
120 pub fn from_json_unchecked(json: &str) -> Self {
121 let trusted_setup = TrustedSetupJSON::from_json_unchecked(json);
122 trusted_setup.to_trusted_setup_unchecked()
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn test_embedded_setup_has_points_in_correct_subgroup() {
132 let setup = TrustedSetupJSON::from_embed();
133 setup.to_trusted_setup();
134 }
135}