Skip to content

Commit 033bc68

Browse files
committed
chore(gnark-key-parser): parse pedersen commitment
Signed-off-by: aeryz <[email protected]>
1 parent a963ff2 commit 033bc68

File tree

3 files changed

+126
-72
lines changed

3 files changed

+126
-72
lines changed

lib/cometbls-groth16-verifier/Cargo.toml

+1-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ version = "0.1.0"
1010
workspace = true
1111

1212
[package.metadata.crane]
13-
include = ["lib/cometbls-groth16-verifier/verifying_key.bin"]
13+
test-include = ["lib/cometbls-groth16-verifier/verifying_key.bin"]
1414

1515
[dependencies]
1616
ark-ff = { version = "0.4.2", default-features = false }
@@ -27,9 +27,5 @@ default = []
2727
std = []
2828

2929
[build-dependencies]
30-
byteorder = { version = "1.4", default-features = false }
3130
gnark-key-parser = { workspace = true }
32-
hex-literal = { workspace = true }
3331
substrate-bn = { version = "0.6", default-features = false }
34-
35-
unionlabs = { workspace = true }
+12-50
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,16 @@
1-
use std::{env, fs, marker::PhantomData, path::Path};
1+
use std::{env, fs, path::Path};
22

3-
use byteorder::BigEndian;
43
use gnark_key_parser::VerifyingKey;
5-
use hex_literal::hex;
64
use substrate_bn::{AffineG1, AffineG2};
7-
use unionlabs::ByteArrayExt;
85

96
pub const FQ_SIZE: usize = 32;
107
pub const G1_SIZE: usize = 2 * FQ_SIZE;
118
pub const G2_SIZE: usize = 2 * G1_SIZE;
129

13-
pub struct G2Affine<FromOrder>(PhantomData<FromOrder>, substrate_bn::AffineG2);
14-
15-
impl<FromOrder> G2Affine<FromOrder> {
16-
fn parse(buf: [u8; G2_SIZE]) -> Self {
17-
G2Affine(
18-
PhantomData,
19-
substrate_bn::AffineG2::new(
20-
substrate_bn::Fq2::new(
21-
substrate_bn::Fq::from_slice(&buf.array_slice::<FQ_SIZE, FQ_SIZE>()).unwrap(),
22-
substrate_bn::Fq::from_slice(&buf.array_slice::<0, FQ_SIZE>()).unwrap(),
23-
),
24-
substrate_bn::Fq2::new(
25-
substrate_bn::Fq::from_slice(
26-
&buf.array_slice::<{ G1_SIZE + FQ_SIZE }, FQ_SIZE>(),
27-
)
28-
.unwrap(),
29-
substrate_bn::Fq::from_slice(&buf.array_slice::<G1_SIZE, FQ_SIZE>()).unwrap(),
30-
),
31-
)
32-
.unwrap(),
33-
)
34-
}
35-
}
36-
3710
fn parse_verifying_key(buf: &[u8]) -> String {
38-
let parsed_key = VerifyingKey::parse(buf).unwrap();
11+
let (n_read, parsed_key) = VerifyingKey::parse(buf).unwrap();
12+
// we expect the verifying key to be fully parsed
13+
assert_eq!(n_read, buf.len());
3914
let [alpha_g1_x0, alpha_g1_x1, alpha_g1_y0, alpha_g1_y1] =
4015
unsafe { std::mem::transmute::<AffineG1, [u128; 4]>(parsed_key.alpha_g1) };
4116
let [beta_g2_x00, beta_g2_x01, beta_g2_x10, beta_g2_x11, beta_g2_y00, beta_g2_y01, beta_g2_y10, beta_g2_y11] =
@@ -44,6 +19,11 @@ fn parse_verifying_key(buf: &[u8]) -> String {
4419
unsafe { std::mem::transmute::<AffineG2, [u128; 8]>(parsed_key.gamma_g2) };
4520
let [delta_g2_x00, delta_g2_x01, delta_g2_x10, delta_g2_x11, delta_g2_y00, delta_g2_y01, delta_g2_y10, delta_g2_y11] =
4621
unsafe { std::mem::transmute::<AffineG2, [u128; 8]>(parsed_key.delta_g2) };
22+
let [pedersen_g_x00, pedersen_g_x01, pedersen_g_x10, pedersen_g_x11, pedersen_g_y00, pedersen_g_y01, pedersen_g_y10, pedersen_g_y11] =
23+
unsafe { std::mem::transmute::<AffineG2, [u128; 8]>(parsed_key.commitment_key.g) };
24+
let [pedersen_g_root_sigma_neg_x00, pedersen_g_root_sigma_neg_x01, pedersen_g_root_sigma_neg_x10, pedersen_g_root_sigma_neg_x11, pedersen_g_root_sigma_neg_y00, pedersen_g_root_sigma_neg_y01, pedersen_g_root_sigma_neg_y10, pedersen_g_root_sigma_neg_y11] = unsafe {
25+
std::mem::transmute::<AffineG2, [u128; 8]>(parsed_key.commitment_key.g_root_sigma_neg)
26+
};
4727

4828
let gamma_abc_size = parsed_key.gamma_abc_g1.len();
4929
let s: String = parsed_key
@@ -66,37 +46,19 @@ fn parse_verifying_key(buf: &[u8]) -> String {
6646
pub const BETA_G2: substrate_bn::AffineG2 = unsafe {{ core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([{beta_g2_x00}, {beta_g2_x01}, {beta_g2_x10}, {beta_g2_x11}, {beta_g2_y00}, {beta_g2_y01}, {beta_g2_y10}, {beta_g2_y11}]) }};
6747
pub const GAMMA_G2: substrate_bn::AffineG2 = unsafe {{ core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([{gamma_g2_x00}, {gamma_g2_x01}, {gamma_g2_x10}, {gamma_g2_x11}, {gamma_g2_y00}, {gamma_g2_y01}, {gamma_g2_y10}, {gamma_g2_y11}]) }};
6848
pub const DELTA_G2: substrate_bn::AffineG2 = unsafe {{ core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([{delta_g2_x00}, {delta_g2_x01}, {delta_g2_x10}, {delta_g2_x11}, {delta_g2_y00}, {delta_g2_y01}, {delta_g2_y10}, {delta_g2_y11}]) }};
49+
pub const PEDERSEN_G: substrate_bn::AffineG2 = unsafe {{ core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([{pedersen_g_x00}, {pedersen_g_x01}, {pedersen_g_x10}, {pedersen_g_x11}, {pedersen_g_y00}, {pedersen_g_y01}, {pedersen_g_y10}, {pedersen_g_y11}]) }};
50+
pub const PEDERSEN_G_ROOT_SIGMA_NEG: substrate_bn::AffineG2 = unsafe {{ core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([{pedersen_g_root_sigma_neg_x00}, {pedersen_g_root_sigma_neg_x01}, {pedersen_g_root_sigma_neg_x10}, {pedersen_g_root_sigma_neg_x11}, {pedersen_g_root_sigma_neg_y00}, {pedersen_g_root_sigma_neg_y01}, {pedersen_g_root_sigma_neg_y10}, {pedersen_g_root_sigma_neg_y11}]) }};
6951
pub const GAMMA_ABC_G1: [substrate_bn::AffineG1; {gamma_abc_size}] = [{s}];
7052
"#
7153
)
7254
}
7355

74-
fn pedersen_commitment_key() -> String {
75-
let g_raw = hex!("257DF6F8132CB0037F7DFDF1A29B04C1FF92BA082EDA513996BA2BFA9FBD198713F0D8D8879885CA567EF99298C30C397E6FBA584658F4127713A814C06DE55A1660EBCC60C7A3AC560EFCEA5993F528EE13685D3A39694ACD74FE67C80D798A15E80642C58DB4DBE0A87F92CE3C65E962F231278353783A691FD64078BA7F34");
76-
let g_root_sigma_neg_raw = hex!("2FBFE141A7555CF7E3E86B092660B81CFB68A025AD817E45CEC0B0F2E2CA636802A104DF1C015F2307FA2859627098CDF9FDB521D61D323943343A12304E5BAF27DA3F93ECF3BFD0B3A3354AE2162A6C230C0E539B6D9F82C0826E2B006A59222C0838551CB9E5CF67DB57DE7E2250BB97807F6687F135A6EB910359BA7BDB8D");
77-
let G2Affine(_, g) = G2Affine::<BigEndian>::parse(g_raw);
78-
let G2Affine(_, g_root_sigma_neg) = G2Affine::<BigEndian>::parse(g_root_sigma_neg_raw);
79-
let [g_g2_x00, g_g2_x01, g_g2_x10, g_g2_x11, g_g2_y00, g_g2_y01, g_g2_y10, g_g2_y11] =
80-
unsafe { std::mem::transmute::<AffineG2, [u128; 8]>(g) };
81-
let [g_root_sigma_neg_g2_x00, g_root_sigma_neg_g2_x01, g_root_sigma_neg_g2_x10, g_root_sigma_neg_g2_x11, g_root_sigma_neg_g2_y00, g_root_sigma_neg_g2_y01, g_root_sigma_neg_g2_y10, g_root_sigma_neg_g2_y11] =
82-
unsafe { std::mem::transmute::<AffineG2, [u128; 8]>(g_root_sigma_neg) };
83-
format!(
84-
r#"
85-
pub const PEDERSEN_G: substrate_bn::AffineG2 = unsafe {{ core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([{g_g2_x00}, {g_g2_x01}, {g_g2_x10}, {g_g2_x11}, {g_g2_y00}, {g_g2_y01}, {g_g2_y10}, {g_g2_y11}]) }};
86-
pub const PEDERSEN_G_ROOT_SIGMA_NEG: substrate_bn::AffineG2 = unsafe {{ core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([{g_root_sigma_neg_g2_x00}, {g_root_sigma_neg_g2_x01}, {g_root_sigma_neg_g2_x10}, {g_root_sigma_neg_g2_x11}, {g_root_sigma_neg_g2_y00}, {g_root_sigma_neg_g2_y01}, {g_root_sigma_neg_g2_y10}, {g_root_sigma_neg_g2_y11}]) }};
87-
"#,
88-
)
89-
}
90-
9156
fn main() {
9257
println!("cargo:rerun-if-changed=verifying_key.bin");
9358
let out_dir = env::var_os("OUT_DIR").unwrap();
9459
let dest_path = Path::new(&out_dir).join("constants.rs");
9560

9661
let data = include_bytes!("./verifying_key.bin");
9762
let verifying_key = parse_verifying_key(data.as_slice());
98-
99-
let pedersen_commitment = pedersen_commitment_key();
100-
101-
fs::write(dest_path, format!("{verifying_key}\n{pedersen_commitment}")).unwrap();
63+
fs::write(dest_path, format!("{verifying_key}")).unwrap();
10264
}

lib/gnark-key-parser/src/lib.rs

+113-17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ use substrate_bn::{
66

77
mod error;
88

9+
pub struct PedersenVerifyingKey {
10+
pub g: AffineG2,
11+
pub g_root_sigma_neg: AffineG2,
12+
}
13+
914
/// A verification key in the Groth16 SNARK.
1015
pub struct VerifyingKey {
1116
/// The `alpha * G`, where `G` is the generator of `E::G1`.
@@ -18,6 +23,8 @@ pub struct VerifyingKey {
1823
pub delta_g2: substrate_bn::AffineG2,
1924
/// The `gamma^{-1} * (beta * a_i + alpha * b_i + c_i) * H`, where `H` is the generator of `E::G1`.
2025
pub gamma_abc_g1: Vec<AffineG1>,
26+
pub public_and_commitment_committed: Vec<Vec<u64>>,
27+
pub commitment_key: PedersenVerifyingKey,
2128
}
2229

2330
const MASK: u8 = 0b11 << 6;
@@ -33,32 +40,72 @@ const G2_AFFINE_COMPRESSED_SIZE: usize = 32 * 2;
3340
const G2_AFFINE_UNCOMPRESSED_SIZE: usize = G2_AFFINE_COMPRESSED_SIZE * 2;
3441

3542
impl VerifyingKey {
36-
pub fn parse(buf: &[u8]) -> Result<Self, Error> {
43+
pub fn parse(buf: &[u8]) -> Result<(usize, Self), Error> {
3744
let mut cursor = 0;
38-
let (n_bytes, alpha_g1) = parse_affine_g1(&buf[..]).unwrap();
45+
let (n_bytes, alpha_g1) = parse_affine_g1(&buf[..])?;
46+
cursor += n_bytes;
47+
let (n_bytes, _g1_beta) = parse_affine_g1(&buf[cursor..])?;
48+
cursor += n_bytes;
49+
let (n_bytes, beta_g2) = parse_affine_g2(&buf[cursor..])?;
50+
cursor += n_bytes;
51+
let (n_bytes, gamma_g2) = parse_affine_g2(&buf[cursor..])?;
52+
cursor += n_bytes;
53+
let (n_bytes, _g1_delta) = parse_affine_g1(&buf[cursor..])?;
3954
cursor += n_bytes;
40-
let (n_bytes, _g1_beta) = parse_affine_g1(&buf[cursor..]).unwrap();
55+
let (n_bytes, delta_g2) = parse_affine_g2(&buf[cursor..])?;
4156
cursor += n_bytes;
42-
let (n_bytes, beta_g2) = parse_affine_g2(&buf[cursor..]).unwrap();
57+
let (n_bytes, gamma_abc_g1) = parse_affine_g1_array(&buf[cursor..])?;
4358
cursor += n_bytes;
44-
let (n_bytes, gamma_g2) = parse_affine_g2(&buf[cursor..]).unwrap();
59+
let (n_bytes, public_and_commitment_committed) = parse_uint64_slice_slice(&buf[cursor..])?;
4560
cursor += n_bytes;
46-
let (n_bytes, _g1_delta) = parse_affine_g1(&buf[cursor..]).unwrap();
61+
let (n_bytes, g) = parse_affine_g2(&buf[cursor..])?;
4762
cursor += n_bytes;
48-
let (n_bytes, delta_g2) = parse_affine_g2(&buf[cursor..]).unwrap();
63+
let (n_bytes, g_root_sigma_neg) = parse_affine_g2(&buf[cursor..])?;
4964
cursor += n_bytes;
50-
let (_, gamma_abc_g1) = parse_affine_g1_array(&buf[cursor..]).unwrap();
51-
52-
Ok(Self {
53-
alpha_g1,
54-
beta_g2,
55-
gamma_g2,
56-
delta_g2,
57-
gamma_abc_g1,
58-
})
65+
66+
Ok((
67+
cursor,
68+
Self {
69+
alpha_g1,
70+
beta_g2,
71+
gamma_g2,
72+
delta_g2,
73+
gamma_abc_g1,
74+
public_and_commitment_committed,
75+
commitment_key: PedersenVerifyingKey {
76+
g,
77+
g_root_sigma_neg,
78+
},
79+
},
80+
))
5981
}
6082
}
6183

84+
pub fn parse_uint64_slice(buf: &[u8]) -> Result<(usize, Vec<u64>), Error> {
85+
let size = u32::from_be_bytes((&buf[0..4]).try_into().expect("impossible"));
86+
let mut items = Vec::new();
87+
let mut cursor = 4;
88+
for _ in 0..size {
89+
items.push(u64::from_be_bytes(
90+
(&buf[cursor..cursor + 8]).try_into().expect("impossible"),
91+
));
92+
cursor += 8;
93+
}
94+
Ok((cursor, items))
95+
}
96+
97+
pub fn parse_uint64_slice_slice(buf: &[u8]) -> Result<(usize, Vec<Vec<u64>>), Error> {
98+
let size = u32::from_be_bytes((&buf[0..4]).try_into().expect("impossible"));
99+
let mut items = Vec::new();
100+
let mut cursor = 4;
101+
for _ in 0..size {
102+
let (cur_read, value) = parse_uint64_slice(&buf[cursor..])?;
103+
cursor += cur_read;
104+
items.push(value);
105+
}
106+
Ok((cursor, items))
107+
}
108+
62109
pub fn parse_affine_g1_array(buf: &[u8]) -> Result<(usize, Vec<AffineG1>), Error> {
63110
let size = u32::from_be_bytes((&buf[0..4]).try_into().expect("impossible"));
64111
let mut g1s = Vec::new();
@@ -263,6 +310,31 @@ mod tests {
263310
}
264311

265312
pub fn universal_vk() -> VerifyingKey {
313+
const PEDERSEN_G: substrate_bn::AffineG2 = unsafe {
314+
core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([
315+
11811635544135052229933151055424244648,
316+
38109979931269619311736752979166931278,
317+
90391742616114872771404285750669801592,
318+
52127860733344004379550038853653983369,
319+
94283382067525625571866539274932825678,
320+
46211394867610833270624710233881181494,
321+
152610685216587622477368049102478160737,
322+
13810267963617699865883949649491963230,
323+
])
324+
};
325+
const PEDERSEN_G_ROOT_SIGMA_NEG: substrate_bn::AffineG2 = unsafe {
326+
core::mem::transmute::<[u128; 8], substrate_bn::AffineG2>([
327+
72813077000167954255887915103454700534,
328+
12589073809616840933661747092291565935,
329+
337926906408442213219854203224585082877,
330+
59919365646951351584569269731816365136,
331+
12528477130055848686709301753705522532,
332+
49609059301297358295345786701940661278,
333+
57099380008375147203174978222963579184,
334+
6628981065425146778130938788258647964,
335+
])
336+
};
337+
266338
VerifyingKey {
267339
alpha_g1: make_g1(
268340
BigInt!(
@@ -340,16 +412,24 @@ mod tests {
340412
),
341413
),
342414
],
415+
public_and_commitment_committed: Vec::new(),
416+
commitment_key: PedersenVerifyingKey {
417+
g: PEDERSEN_G,
418+
g_root_sigma_neg: PEDERSEN_G_ROOT_SIGMA_NEG,
419+
},
343420
}
344421
}
422+
345423
#[test]
346424
fn it_works() {
347425
// vk.bin
348426
let file = hex::decode("8967072901cc7ab63357f1ddc4196c7c1feda50540d8026d7f6f0167c118a899d923def15f75234f2a6d53b566a2528441e98050b38803673e9179b834fc39a499355fd270b7601d5d88408b7e9e53d260512e2180cd260017dc941f2fc96d65153f0344c6bf2d8a891b979bc61d39a98fb11155fcd57418f30ea018ea842874a0e76be91a3148e2f8ef644222b3ce5b939a73bd2e0a40814f7f92a79c483acf2216bbe0c289e07936b4d9653b91521a24c570c808fa46dfd12ec4429e71b61999fcfb245459d63a4923b8f8c488d1e6af7ca358867b88eb0cdefe896c221f09e95e4c18d1e0475de4549b2547611d8301e1afff1047a6f5a288c9314af0b9fc05d403c8c91820a385a72c18d6a4962cef41a3ab93daa7ed289b1e95db4d04eb00000003e71843e52743864f4bb67ce94a2ce8fe82c8f61042c4c1ced8531d94305392818b0dbe71f4d60e02e9160ec2b015cae3a09cbe4f437226e2c02e1a5e5d124bcac29e93d5f47c0c7671350398ed8c40f5bc5c2f5b00363c7e2eb18a91a1c490c70000000100000000a57df6f8132cb0037f7dfdf1a29b04c1ff92ba082eda513996ba2bfa9fbd198713f0d8d8879885ca567ef99298c30c397e6fba584658f4127713a814c06de55aefbfe141a7555cf7e3e86b092660b81cfb68a025ad817e45cec0b0f2e2ca636802a104df1c015f2307fa2859627098cdf9fdb521d61d323943343a12304e5baf").unwrap();
349427

350428
let verifying_key = universal_vk();
351429

352-
let parsed_key = VerifyingKey::parse(&file[..]).unwrap();
430+
let (n_read, parsed_key) = VerifyingKey::parse(&file[..]).unwrap();
431+
432+
assert_eq!(n_read, file.len());
353433

354434
assert_eq!(verifying_key.alpha_g1, parsed_key.alpha_g1);
355435
assert_eq!(verifying_key.beta_g2.x(), parsed_key.beta_g2.x());
@@ -359,5 +439,21 @@ mod tests {
359439
assert_eq!(verifying_key.delta_g2.x(), parsed_key.delta_g2.x());
360440
assert_eq!(verifying_key.delta_g2.y(), parsed_key.delta_g2.y());
361441
assert_eq!(verifying_key.gamma_abc_g1, parsed_key.gamma_abc_g1);
442+
assert_eq!(
443+
verifying_key.commitment_key.g.x(),
444+
parsed_key.commitment_key.g.x()
445+
);
446+
assert_eq!(
447+
verifying_key.commitment_key.g.y(),
448+
parsed_key.commitment_key.g.y()
449+
);
450+
assert_eq!(
451+
verifying_key.commitment_key.g_root_sigma_neg.x(),
452+
parsed_key.commitment_key.g_root_sigma_neg.x()
453+
);
454+
assert_eq!(
455+
verifying_key.commitment_key.g_root_sigma_neg.y(),
456+
parsed_key.commitment_key.g_root_sigma_neg.y()
457+
);
362458
}
363459
}

0 commit comments

Comments
 (0)