1
1
const fs = require ( "fs" ) ;
2
+ const bb = require ( "bigint-buffer" ) ;
3
+ const ff = require ( "ffjavascript" ) ;
2
4
3
5
const proof = JSON . parse ( fs . readFileSync ( "proof.json" , "utf-8" ) ) ;
4
6
const verificationKey = JSON . parse ( fs . readFileSync ( "verification_key.json" , "utf-8" ) ) ;
5
7
6
- console . log ( "Proof" , JSON . stringify ( proof ) ) ;
8
+ async function compressedG1 ( point ) {
9
+ const curve = await ff . getCurveFromName ( "bls12381" ) ;
7
10
8
- function uncompressedFq ( number ) {
9
- const buffer = Buffer . alloc ( 48 ) ;
10
- buffer . write ( BigInt ( number ) . toString ( 16 ) , 0 , 48 , "hex" ) ;
11
- return buffer . toString ( "hex" ) ;
12
- }
11
+ const result = bb . toBufferBE ( BigInt ( point [ 0 ] ) , 48 ) ;
12
+ const COMPRESSED = 0b10000000 ;
13
+ const INFINITY = 0b01000000 ;
14
+ const YBIT = 0b00100000 ;
15
+
16
+ result [ 0 ] = result [ 0 ] | COMPRESSED ;
17
+
18
+ if ( BigInt ( point [ 2 ] ) !== 1n ) {
19
+ result [ 0 ] = result [ 0 ] | INFINITY ;
20
+ } else {
21
+ const F = curve . G1 . F ;
22
+
23
+ const x = F . fromObject ( BigInt ( point [ 0 ] ) ) ;
24
+
25
+ const x3b = F . add ( F . mul ( F . square ( x ) , x ) , curve . G1 . b ) ;
26
+ const y1 = F . toObject ( F . sqrt ( x3b ) ) ;
27
+ const y2 = F . toObject ( F . neg ( F . sqrt ( x3b ) ) ) ;
28
+
29
+ const y = BigInt ( point [ 1 ] ) ;
13
30
14
- function uncompressedG1 ( point ) {
15
- const x = uncompressedFq ( point [ 0 ] ) ;
16
- return x ;
31
+ if ( y1 > y2 && y > y2 ) {
32
+ result [ 0 ] = result [ 0 ] | YBIT ;
33
+ } else if ( y1 < y2 && y > y1 ) {
34
+ result [ 0 ] = result [ 0 ] | YBIT ;
35
+ }
36
+ }
37
+
38
+
39
+ return result . toString ( "hex" ) ;
17
40
}
18
41
19
- function uncompressedG2 ( point ) {
20
- const x = uncompressedFq ( point [ 0 ] [ 0 ] ) + uncompressedFq ( point [ 0 ] [ 1 ] ) ;
21
- return x ;
42
+ async function compressedG2 ( point ) {
43
+ const curve = await ff . getCurveFromName ( "bls12381" ) ;
44
+
45
+ const result = Buffer . concat ( [ bb . toBufferBE ( BigInt ( point [ 0 ] [ 1 ] ) , 48 ) , bb . toBufferBE ( BigInt ( point [ 0 ] [ 0 ] ) , 48 ) ] ) ;
46
+ const COMPRESSED = 0b10000000 ;
47
+ const INFINITY = 0b01000000 ;
48
+ const YBIT = 0b00100000 ;
49
+
50
+ result [ 0 ] = result [ 0 ] | COMPRESSED ;
51
+
52
+ if ( BigInt ( point [ 2 ] [ 0 ] ) !== 1n ) {
53
+ result [ 0 ] = result [ 0 ] | INFINITY ;
54
+ } else {
55
+ const F = curve . G2 . F ;
56
+
57
+ const x = F . fromObject ( point [ 0 ] . map ( item => BigInt ( item ) ) ) ;
58
+
59
+ // console.log("x", x);
60
+
61
+ const x3b = F . add ( F . mul ( F . square ( x ) , x ) , curve . G2 . b ) ;
62
+ const y1 = F . toObject ( F . sqrt ( x3b ) ) ;
63
+ const y2 = F . toObject ( F . neg ( F . sqrt ( x3b ) ) ) ;
64
+ // console.log("y1", y1);
65
+ // console.log("y2", y2);
66
+ // console.log("point", point[1]);
67
+
68
+ function greaterThan ( a , b ) {
69
+ if ( a [ 1 ] > b [ 1 ] ) {
70
+ return true
71
+ } else if ( a [ 1 ] === b [ 1 ] && a [ 0 ] > b [ 0 ] ) {
72
+ return true ;
73
+ }
74
+ return false ;
75
+ }
76
+
77
+ const y = point [ 1 ] . map ( item => BigInt ( item ) ) ;
78
+
79
+ if ( greaterThan ( y1 , y2 ) && greaterThan ( y , y2 ) ) {
80
+ result [ 0 ] = result [ 0 ] | YBIT ;
81
+ } else if ( greaterThan ( y2 , y1 ) && greaterThan ( y , y1 ) ) {
82
+ result [ 0 ] = result [ 0 ] | YBIT ;
83
+ }
84
+ }
85
+ return result . toString ( "hex" ) ;
22
86
}
23
87
24
- function convertProofToUncompressed ( proof ) {
88
+
89
+ async function convertProofToUncompressed ( proof ) {
25
90
26
91
const uncompressedProof = {
27
- "pi_a" : uncompressedG1 ( proof . pi_a ) ,
28
- "pi_b" : uncompressedG2 ( proof . pi_b ) ,
29
- "pi_c" : uncompressedG1 ( proof . pi_c ) ,
92
+ "pi_a" : await compressedG1 ( proof . pi_a ) ,
93
+ "pi_b" : await compressedG2 ( proof . pi_b ) ,
94
+ "pi_c" : await compressedG1 ( proof . pi_c ) ,
30
95
}
31
96
32
97
return uncompressedProof ;
33
98
}
34
99
35
100
36
- function convertVerificationKeyToUncompressed ( verificationKey ) {
101
+ async function convertVerificationKeyToUncompressed ( verificationKey ) {
37
102
const uncompressedVerificationKey = {
38
- "vk_alpha_1" : uncompressedG1 ( verificationKey . vk_alpha_1 ) ,
39
- "vk_beta_2" : uncompressedG2 ( verificationKey . vk_beta_2 ) ,
40
- "vk_gamma_2" : uncompressedG2 ( verificationKey . vk_gamma_2 ) ,
41
- "vk_delta_2" : uncompressedG2 ( verificationKey . vk_delta_2 ) ,
42
- "IC" : verificationKey . IC . map ( ( item ) => uncompressedG1 ( item ) ) ,
103
+ "vk_alpha_1" : await compressedG1 ( verificationKey . vk_alpha_1 ) ,
104
+ "vk_beta_2" : await compressedG2 ( verificationKey . vk_beta_2 ) ,
105
+ "vk_gamma_2" : await compressedG2 ( verificationKey . vk_gamma_2 ) ,
106
+ "vk_delta_2" : await compressedG2 ( verificationKey . vk_delta_2 ) ,
107
+ "IC" : verificationKey . IC . map ( async ( item ) => await compressedG1 ( item ) ) ,
43
108
}
44
109
45
110
return uncompressedVerificationKey ;
46
111
}
47
112
48
- console . log ( "Uncompressed proof" , JSON . stringify ( convertProofToUncompressed ( proof ) ) ) ;
113
+ async function printCompressedProof ( ) {
114
+ console . log ( "Compressed proof" , JSON . stringify ( await convertProofToUncompressed ( proof ) ) ) ;
115
+ }
116
+
117
+ printCompressedProof ( ) ;
49
118
50
- console . log ( "\n\nUncompressed verification key" , JSON . stringify ( convertVerificationKeyToUncompressed ( verificationKey ) ) ) ;
119
+ async function printCompressedVerificationKey ( ) {
120
+ console . log ( "\n\nUncompressed verification key" , JSON . stringify ( await convertVerificationKeyToUncompressed ( verificationKey ) ) ) ;
121
+ }
122
+
123
+ printCompressedVerificationKey ( ) ;
124
+
125
+
126
+ async function ffTest ( ) {
127
+ const curve = await ff . getCurveFromName ( "bls12381" ) ;
128
+
129
+ const point = proof . pi_c ;
130
+
131
+ const xBufferBE = bb . toBufferBE ( BigInt ( point [ 0 ] ) , 48 ) ;
132
+
133
+ console . log ( "Point x buffer BE" , new Uint8Array ( xBufferBE ) ) ;
134
+
135
+ const xBufferLE = bb . toBufferLE ( BigInt ( point [ 0 ] ) , 48 ) ;
136
+
137
+ console . log ( "Point x buffer LE" , new Uint8Array ( xBufferLE ) ) ;
138
+
139
+
140
+ const g1Element = curve . G1 . fromObject ( point . map ( ( item ) => BigInt ( item ) . toString ( 16 ) ) ) ;
141
+
142
+ console . log ( "G1 element" , g1Element ) ;
143
+
144
+ console . log ( "G1 Element is valid" , curve . G1 . isValid ( g1Element ) ) ;
145
+
146
+ const buff = new Uint8Array ( 48 ) ;
147
+
148
+ curve . G1 . toRprCompressed ( buff , 0 , g1Element ) ;
149
+
150
+ console . log ( "G1 element Compressed" , buff ) ;
151
+
152
+ console . log ( "MSB" , buff [ 0 ] . toString ( 2 ) ) ;
153
+
154
+ const g1ElementFromCompressed = curve . G1 . fromRprCompressed ( buff , 0 ) ;
155
+
156
+ console . log ( "G1 from compressed" , g1ElementFromCompressed ) ;
157
+
158
+ console . log ( "G1 from compressed is valid" , curve . G1 . isValid ( g1ElementFromCompressed ) ) ;
159
+ }
51
160
161
+ // ffTest();
0 commit comments