Skip to main content

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}