|
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