|
1 |
| -extern crate bn; |
| 1 | +extern crate ethereum_bn128; |
| 2 | +extern crate parity_bytes as bytes; |
2 | 3 | extern crate rustc_hex;
|
3 | 4 |
|
4 | 5 | use std::os::raw::c_char;
|
5 | 6 | use std::ffi::CStr;
|
6 | 7 |
|
7 | 8 | use rustc_hex::FromHex;
|
8 | 9 | use rustc_hex::ToHex;
|
9 |
| -use std::io::{self, Read}; |
10 | 10 |
|
11 |
| -#[derive(Debug)] |
12 |
| -pub struct Error(pub &'static str); |
13 |
| - |
14 |
| -impl From<&'static str> for Error { |
15 |
| - fn from(val: &'static str) -> Self { |
16 |
| - Error(val) |
17 |
| - } |
18 |
| -} |
19 |
| - |
20 |
| -fn read_fr(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::Fr, Error> { |
21 |
| - use bn::Fr; |
22 |
| - let mut buf = [0u8; 32]; |
23 |
| - reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); |
24 |
| - Fr::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid field element")) |
25 |
| -} |
26 |
| - |
27 |
| - |
28 |
| -fn read_point(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::G1, Error> { |
29 |
| - use bn::{Fq, AffineG1, G1, Group}; |
30 |
| - |
31 |
| - let mut buf = [0u8; 32]; |
32 |
| - |
33 |
| - reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); |
34 |
| - let px = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point x coordinate"))?; |
35 |
| - |
36 |
| - reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); |
37 |
| - let py = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point y coordinate"))?; |
38 |
| - |
39 |
| - Ok( |
40 |
| - if px == Fq::zero() && py == Fq::zero() { |
41 |
| - G1::zero() |
42 |
| - } else { |
43 |
| - AffineG1::new(px, py).map_err(|_| Error::from("Invalid curve point"))?.into() |
44 |
| - } |
45 |
| - ) |
46 |
| -} |
| 11 | +use bytes::BytesRef; |
47 | 12 |
|
48 | 13 | #[no_mangle]
|
49 | 14 | pub fn ec_mul(input_hex_ptr: *const c_char) -> *const c_char {
|
50 |
| - use bn::AffineG1; |
51 |
| - |
52 | 15 | let input_hex = unsafe { CStr::from_ptr(input_hex_ptr) };
|
53 | 16 | let input_str: &str = input_hex.to_str().unwrap();
|
54 | 17 | let input_parsed = FromHex::from_hex(input_str).unwrap();
|
55 |
| - let mut padded_input = input_parsed.chain(io::repeat(0)); |
56 | 18 |
|
57 |
| - let p1; |
58 |
| - match read_point(&mut padded_input) { |
59 |
| - Ok(p) => { p1 = p; }, |
60 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
61 |
| - } |
62 |
| - |
63 |
| - let fr; |
64 |
| - match read_fr(&mut padded_input) { |
65 |
| - Ok(f) => { fr = f; }, |
66 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
67 |
| - } |
68 |
| - |
69 |
| - let mut ecmul_output_buf = [0u8; 64]; |
70 |
| - if let Some(sum) = AffineG1::from_jacobian(p1 * fr) { |
71 |
| - // point not at infinity |
72 |
| - sum.x().to_big_endian(&mut ecmul_output_buf[0..32]).expect("Cannot fail since 0..32 is 32-byte length"); |
73 |
| - sum.y().to_big_endian(&mut ecmul_output_buf[32..64]).expect("Cannot fail since 32..64 is 32-byte length");; |
| 19 | + let mut output = vec![0u8; 64]; |
| 20 | + match ethereum_bn128::bn128_mul(&input_parsed[..], &mut BytesRef::Fixed(&mut output[..])) { |
| 21 | + Ok(_) => { |
| 22 | + let mut output_hex = output.to_hex(); |
| 23 | + output_hex.push_str("\0"); |
| 24 | + return output_hex.as_ptr() as *const c_char |
| 25 | + } |
| 26 | + Err(_) => { |
| 27 | + return "\0".as_ptr() as *const c_char |
| 28 | + } |
74 | 29 | }
|
75 |
| - |
76 |
| - let mut ec_mul_output_str = ecmul_output_buf.to_hex(); |
77 |
| - ec_mul_output_str.push_str("\0"); |
78 |
| - return ec_mul_output_str.as_ptr() as *const c_char |
79 | 30 | }
|
80 | 31 |
|
81 |
| - |
82 | 32 | #[no_mangle]
|
83 | 33 | pub fn ec_add(input_hex_ptr: *const c_char) -> *const c_char {
|
84 |
| - use bn::AffineG1; |
85 |
| - |
86 | 34 | let input_hex = unsafe { CStr::from_ptr(input_hex_ptr) };
|
87 | 35 | let input_str: &str = input_hex.to_str().unwrap();
|
88 | 36 | let input_parsed = FromHex::from_hex(input_str).unwrap();
|
89 |
| - let mut padded_input = input_parsed.chain(io::repeat(0)); |
90 |
| - |
91 |
| - let mut padded_buf = [0u8; 128]; |
92 |
| - padded_input.read_exact(&mut padded_buf[..]).expect("reading from zero-extended memory cannot fail; qed"); |
93 |
| - |
94 |
| - let point1 = &padded_buf[0..64]; |
95 |
| - let point2 = &padded_buf[64..128]; |
96 |
| - |
97 |
| - let mut point1_padded = point1.chain(io::repeat(0)); |
98 |
| - let mut point2_padded = point2.chain(io::repeat(0)); |
99 |
| - |
100 |
| - let p1; |
101 |
| - match read_point(&mut point1_padded) { |
102 |
| - Ok(p) => { |
103 |
| - p1 = p; |
104 |
| - }, |
105 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
106 |
| - } |
107 |
| - |
108 |
| - match read_point(&mut point2_padded) { |
109 |
| - Ok(p) => { |
110 |
| - let p2 = p; |
111 |
| - let mut ecadd_output_buf = [0u8; 64]; |
112 |
| - if let Some(sum) = AffineG1:: from_jacobian(p1 + p2) { |
113 |
| - sum.x().to_big_endian(&mut ecadd_output_buf[0..32]).expect("Cannot fail since 0..32 is 32-byte length"); |
114 |
| - sum.y().to_big_endian(&mut ecadd_output_buf[32..64]).expect("Cannot fail since 32..64 is 32-byte length");; |
115 |
| - } |
116 |
| - let mut ec_add_output_str = ecadd_output_buf.to_hex(); |
117 |
| - ec_add_output_str.push_str("\0"); |
118 |
| - return ec_add_output_str.as_ptr() as *const c_char |
119 |
| - }, |
120 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
121 |
| - } |
122 | 37 |
|
| 38 | + let mut output = vec![0u8; 64]; |
| 39 | + match ethereum_bn128::bn128_add(&input_parsed[..], &mut BytesRef::Fixed(&mut output[..])) { |
| 40 | + Ok(_) => { |
| 41 | + let mut output_hex = output.to_hex(); |
| 42 | + output_hex.push_str("\0"); |
| 43 | + return output_hex.as_ptr() as *const c_char |
| 44 | + } |
| 45 | + Err(_) => { |
| 46 | + return "\0".as_ptr() as *const c_char |
| 47 | + } |
| 48 | + } |
123 | 49 | }
|
124 | 50 |
|
125 | 51 | #[no_mangle]
|
126 | 52 | pub fn ec_pairing(input_hex_ptr: *const c_char) -> *const c_char {
|
127 |
| - use bn::{Fq, Fq2, G1, G2, Gt, AffineG1, AffineG2, Group, pairing}; |
128 |
| - |
129 | 53 | let input_hex = unsafe { CStr::from_ptr(input_hex_ptr) };
|
130 | 54 | let input_str: &str = input_hex.to_str().unwrap();
|
131 |
| - let input = FromHex::from_hex(input_str).unwrap(); |
132 |
| - //println!("input: {:?}", input); |
133 |
| - |
134 |
| - let elements = input.len() / 192; |
135 |
| - |
136 |
| - if input.len() % 192 != 0 { |
137 |
| - return "\0".as_ptr() as *const c_char; |
138 |
| - } |
139 |
| - |
140 |
| - let ret_val = if input.len() == 0 { |
141 |
| - bn::arith::U256::one() |
142 |
| - } else { |
143 |
| - let mut vals = Vec::new(); |
144 |
| - |
145 |
| - for idx in 0..elements { |
146 |
| - let x_1; |
147 |
| - match Fq::from_slice(&input[idx*192..idx*192+32]) { |
148 |
| - Ok(fq) => { x_1 = fq }, |
149 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
150 |
| - } |
151 |
| - |
152 |
| - let y_1; |
153 |
| - match Fq::from_slice(&input[idx*192+32..idx*192+64]) { |
154 |
| - Ok(fq) => { y_1 = fq }, |
155 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
156 |
| - } |
157 |
| - |
158 |
| - let x2_i; |
159 |
| - match Fq::from_slice(&input[idx*192+64..idx*192+96]) { |
160 |
| - Ok(fq) => { x2_i = fq }, |
161 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
162 |
| - } |
163 |
| - |
164 |
| - let x2_r; |
165 |
| - match Fq::from_slice(&input[idx*192+96..idx*192+128]) { |
166 |
| - Ok(fq) => { x2_r = fq }, |
167 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
168 |
| - } |
169 |
| - |
170 |
| - let y2_i; |
171 |
| - match Fq::from_slice(&input[idx*192+128..idx*192+160]) { |
172 |
| - Ok(fq) => { y2_i = fq }, |
173 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
174 |
| - } |
175 |
| - |
176 |
| - let y2_r; |
177 |
| - match Fq::from_slice(&input[idx*192+160..idx*192+192]) { |
178 |
| - Ok(fq) => { y2_r = fq }, |
179 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
180 |
| - } |
181 |
| - |
182 |
| - //println!("creating g1_point with x1 and y1..."); |
183 |
| - //println!("x1: {:?} y1: {:?}", x_1, y_1); |
184 |
| - |
185 |
| - let g1_point; |
186 |
| - if x_1 == Fq::zero() && y_1 == Fq::zero() { |
187 |
| - g1_point = G1::zero(); |
188 |
| - } else { |
189 |
| - match AffineG1::new(x_1, y_1) { |
190 |
| - Ok(ap) => { |
191 |
| - let g1_affine_point = ap; |
192 |
| - g1_point = G1::from(g1_affine_point); |
193 |
| - }, |
194 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
195 |
| - } |
196 |
| - } |
197 |
| - |
198 |
| - /* |
199 |
| - let mut g1_point_x_buf = [0u8; 32]; |
200 |
| - let mut g1_point_y_buf = [0u8; 32]; |
201 |
| - g1_point.x().to_big_endian(&mut g1_point_x_buf[0..32]); |
202 |
| - println!("g1_point.x(): {:?}", g1_point_x_buf.to_hex()); |
203 |
| - g1_point.y().to_big_endian(&mut g1_point_y_buf[0..32]); |
204 |
| - println!("g1_point.y(): {:?}", g1_point_y_buf.to_hex()); |
205 |
| - */ |
206 |
| - |
207 |
| - let fq2_x = Fq2::new(x2_r, x2_i); |
208 |
| - let fq2_y = Fq2::new(y2_r, y2_i); |
209 |
| - |
210 |
| - let g2_point; |
211 |
| - if x2_r.is_zero() && x2_i.is_zero() && y2_r.is_zero() && y2_i.is_zero() { |
212 |
| - g2_point = G2::zero(); |
213 |
| - } else { |
214 |
| - match AffineG2::new(fq2_x, fq2_y) { |
215 |
| - Ok (ap) => { |
216 |
| - let g2_affine_point = ap; |
217 |
| - g2_point = G2::from(g2_affine_point); |
218 |
| - }, |
219 |
| - Err(_) => { return "\0".as_ptr() as *const c_char } |
220 |
| - } |
221 |
| - } |
222 |
| - |
223 |
| - vals.push((g1_point, g2_point)); |
224 |
| - }; |
| 55 | + let input_parsed = FromHex::from_hex(input_str).unwrap(); |
225 | 56 |
|
226 |
| - let mul = vals.into_iter().fold(Gt::one(), |s, (a, b)| s * pairing(a, b)); |
227 |
| - if mul == Gt::one() { |
228 |
| - bn::arith::U256::one() |
229 |
| - } else { |
230 |
| - bn::arith::U256::zero() |
| 57 | + let mut output = vec![0u8; 32]; |
| 58 | + match ethereum_bn128::bn128_pairing(&input_parsed[..], &mut BytesRef::Fixed(&mut output[..])) { |
| 59 | + Ok(_) => { |
| 60 | + let mut output_hex = output.to_hex(); |
| 61 | + output_hex.push_str("\0"); |
| 62 | + return output_hex.as_ptr() as *const c_char |
231 | 63 | }
|
232 |
| - }; |
233 |
| - |
234 |
| - let mut ec_pairing_output_buf = [0u8; 32]; |
235 |
| - ret_val.to_big_endian(&mut ec_pairing_output_buf).expect("Cannot fail since buf is 32-byte length"); |
236 |
| - let mut ec_pairing_output_str = ec_pairing_output_buf.to_hex(); |
237 |
| - //println!("ec_pairing_output_str: {:?}", ec_pairing_output_str); |
238 |
| - |
239 |
| - ec_pairing_output_str.push_str("\0"); |
240 |
| - return ec_pairing_output_str.as_ptr() as *const c_char |
| 64 | + Err(_) => { |
| 65 | + return "\0".as_ptr() as *const c_char |
| 66 | + } |
| 67 | + } |
241 | 68 | }
|
242 | 69 |
|
243 |
| - |
244 |
| - |
245 | 70 | extern {
|
246 | 71 | fn emscripten_exit_with_live_runtime();
|
247 | 72 | }
|
248 | 73 |
|
249 |
| - |
250 | 74 | fn main() {
|
251 | 75 | unsafe {
|
252 | 76 | emscripten_exit_with_live_runtime();
|
253 | 77 | }
|
254 |
| - |
255 | 78 | }
|
0 commit comments