Skip to content

Commit 2829dac

Browse files
committed
add altbn128 and ipa-multipoint to linux-arm64 build
Signed-off-by: garyschulte <garyschulte@gmail.com>
1 parent f197cb4 commit 2829dac

File tree

5 files changed

+256
-9
lines changed

5 files changed

+256
-9
lines changed

.circleci/config.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,16 @@ jobs:
135135
- persist_to_workspace:
136136
root: .
137137
paths:
138+
- altbn128/build/lib/*.so*
138139
- secp256k1/build/lib/*.so*
140+
- ipa-multipoint/build/lib/*.so
139141
- secp256r1/besu-native-ec/release/*.so
140142
- store_artifacts:
143+
name: Linux altbn128 native build artifacts
144+
path: altbn128/build/lib
145+
destination: altbn128_linux_aarch64_native_artifacts
146+
when: always
147+
] - store_artifacts:
141148
name: Linux secp256k1 native build artifacts
142149
path: secp256k1/build/lib
143150
destination: secp256k1_linux_aarch64_native_artifacts
@@ -147,6 +154,11 @@ jobs:
147154
path: secp256r1/besu-native-ec/release
148155
destination: secp256r1_linux_aarch64_native_artifacts
149156
when: always
157+
- store_artifacts:
158+
name: Linux ipa-multipoint native build artifacts
159+
path: ipa-multipoint/build/lib
160+
destination: ipa_multipoint_linux_aarch64_native_artifacts
161+
when: always
150162
native-build-macos:
151163
executor: besu_executor_med_macos
152164
environment:

altbn128/sputnikvm_altbn128/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ edition = "2018"
1010
[dependencies]
1111
ethereum-bigint = { version = "0.2", default-features = false }
1212
bn-plus = { version = "0.4.4" }
13+
libc = "0.2"
1314

1415
[lib]
1516
name = "eth_altbn128"

altbn128/sputnikvm_altbn128/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ pub extern "C" fn altbn128_add_precompiled(
1717
o: *mut ::std::os::raw::c_char,
1818
o_len: *mut u32,
1919
) -> u32 {
20-
let input_i8: &[i8] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
20+
let input_i8: &[libc::c_char] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
2121
let input: &[u8] = unsafe { std::mem::transmute(input_i8) };
2222

23-
let raw_out_i8: &mut [i8] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
23+
let raw_out_i8: &mut [libc::c_char] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
2424
let mut raw_out: &mut [u8] = unsafe { std::mem::transmute(raw_out_i8) };
2525

2626
return match altbn128_add_precompiled_impl(input) {
@@ -88,10 +88,10 @@ pub extern "C" fn altbn128_mul_precompiled(
8888
o: *mut ::std::os::raw::c_char,
8989
o_len: *mut u32,
9090
) -> u32 {
91-
let input_i8: &[i8] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
91+
let input_i8: &[libc::c_char] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
9292
let input: &[u8] = unsafe { std::mem::transmute(input_i8) };
9393

94-
let raw_out_i8: &mut [i8] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
94+
let raw_out_i8: &mut [libc::c_char] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
9595
let mut raw_out: &mut [u8] = unsafe { std::mem::transmute(raw_out_i8) };
9696

9797
return match altbn128_mul_precompiled_impl(input) {
@@ -151,10 +151,10 @@ pub extern "C" fn altbn128_pairing_precompiled(
151151
o: *mut ::std::os::raw::c_char,
152152
o_len: *mut u32,
153153
) -> u32 {
154-
let input_i8: &[i8] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
154+
let input_i8: &[libc::c_char] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
155155
let input: &[u8] = unsafe { std::mem::transmute(input_i8) };
156156

157-
let raw_out_i8: &mut [i8] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
157+
let raw_out_i8: &mut [libc::c_char] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
158158
let mut raw_out: &mut [u8] = unsafe { std::mem::transmute(raw_out_i8) };
159159

160160
return match altbn128_pairing_precompiled_impl(input) {
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
// Derived from SputnikVM
2+
// https://github.com/ETCDEVTeam/sputnikvm/blob/8ce6d085a0773196a198400ca9721e19bd7ed8a0/precompiled/bn128/src/lib.rs
3+
// SPDX-License-Identifier: Apache-2.0
4+
use std::rc::Rc;
5+
use std::io::Write;
6+
7+
#[derive(Debug, Clone)]
8+
pub enum RuntimeError {
9+
/// Input was a bad format.
10+
BadFormat,
11+
}
12+
13+
#[no_mangle]
14+
pub extern "C" fn altbn128_add_precompiled(
15+
i: *const ::std::os::raw::c_char,
16+
i_len: u32,
17+
o: *mut ::std::os::raw::c_char,
18+
o_len: *mut u32,
19+
) -> u32 {
20+
let input_i8: &[i8] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
21+
let input: &[u8] = unsafe { std::mem::transmute(input_i8) };
22+
23+
let raw_out_i8: &mut [i8] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
24+
let mut raw_out: &mut [u8] = unsafe { std::mem::transmute(raw_out_i8) };
25+
26+
return match altbn128_add_precompiled_impl(input) {
27+
Ok(result) => {
28+
let written = raw_out.write(result.as_ref());
29+
if let Ok(bytes_written) = written {
30+
unsafe { *o_len = bytes_written as u32 };
31+
0u32
32+
} else {
33+
1u32
34+
}
35+
}
36+
Err(_error) => {
37+
1u32
38+
}
39+
}
40+
}
41+
42+
fn altbn128_add_precompiled_impl(data: &[u8]) -> Result<Rc<Vec<u8>>, RuntimeError> {
43+
use bn::{AffineG1, Fq, Group, G1};
44+
45+
// Padding data to be at least 32 * 4 bytes.
46+
let mut data: Vec<u8> = data.into();
47+
while data.len() < 32 * 4 {
48+
data.push(0);
49+
}
50+
51+
let px =
52+
Fq::from_slice(&data[0..32]).map_err(|_| RuntimeError::BadFormat)?;
53+
let py =
54+
Fq::from_slice(&data[32..64]).map_err(|_| RuntimeError::BadFormat)?;
55+
let qx =
56+
Fq::from_slice(&data[64..96]).map_err(|_| RuntimeError::BadFormat)?;
57+
let qy = Fq::from_slice(&data[96..128])
58+
.map_err(|_| RuntimeError::BadFormat)?;
59+
60+
let p = if px == Fq::zero() && py == Fq::zero() {
61+
G1::zero()
62+
} else {
63+
AffineG1::new(px, py)
64+
.map_err(|_| RuntimeError::BadFormat)?
65+
.into()
66+
};
67+
let q = if qx == Fq::zero() && qy == Fq::zero() {
68+
G1::zero()
69+
} else {
70+
AffineG1::new(qx, qy)
71+
.map_err(|_| RuntimeError::BadFormat)?
72+
.into()
73+
};
74+
75+
let mut output = vec![0u8; 64];
76+
if let Some(ret) = AffineG1::from_jacobian(p + q) {
77+
ret.x().to_big_endian(&mut output[0..32]).unwrap();
78+
ret.y().to_big_endian(&mut output[32..64]).unwrap();
79+
}
80+
81+
Ok(Rc::new(output))
82+
}
83+
84+
#[no_mangle]
85+
pub extern "C" fn altbn128_mul_precompiled(
86+
i: *const ::std::os::raw::c_char,
87+
i_len: u32,
88+
o: *mut ::std::os::raw::c_char,
89+
o_len: *mut u32,
90+
) -> u32 {
91+
let input_i8: &[i8] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
92+
let input: &[u8] = unsafe { std::mem::transmute(input_i8) };
93+
94+
let raw_out_i8: &mut [i8] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
95+
let mut raw_out: &mut [u8] = unsafe { std::mem::transmute(raw_out_i8) };
96+
97+
return match altbn128_mul_precompiled_impl(input) {
98+
Ok(result) => {
99+
let written = raw_out.write(result.as_ref());
100+
if let Ok(bytes_written) = written {
101+
unsafe { *o_len = bytes_written as u32 };
102+
0u32
103+
} else {
104+
1u32
105+
}
106+
}
107+
Err(_error) => {
108+
1u32
109+
}
110+
}
111+
}
112+
113+
fn altbn128_mul_precompiled_impl(data: &[u8]) -> Result<Rc<Vec<u8>>, RuntimeError> {
114+
use bn::{AffineG1, Fq, Fr, Group, G1};
115+
116+
// Padding data to be at least 32 * 4 bytes.
117+
let mut data: Vec<u8> = data.into();
118+
while data.len() < 32 * 3 {
119+
data.push(0);
120+
}
121+
122+
let px =
123+
Fq::from_slice(&data[0..32]).map_err(|_| RuntimeError::BadFormat)?;
124+
let py =
125+
Fq::from_slice(&data[32..64]).map_err(|_| RuntimeError::BadFormat)?;
126+
let fr =
127+
Fr::from_slice(&data[64..96]).map_err(|_| RuntimeError::BadFormat)?;
128+
129+
let p = if px == Fq::zero() && py == Fq::zero() {
130+
G1::zero()
131+
} else {
132+
AffineG1::new(px, py)
133+
.map_err(|_| RuntimeError::BadFormat)?
134+
.into()
135+
};
136+
137+
let mut output = vec![0u8; 64];
138+
if let Some(ret) = AffineG1::from_jacobian(p * fr) {
139+
ret.x().to_big_endian(&mut output[0..32]).unwrap();
140+
ret.y().to_big_endian(&mut output[32..64]).unwrap();
141+
};
142+
143+
Ok(Rc::new(output))
144+
}
145+
146+
147+
#[no_mangle]
148+
pub extern "C" fn altbn128_pairing_precompiled(
149+
i: *const ::std::os::raw::c_char,
150+
i_len: u32,
151+
o: *mut ::std::os::raw::c_char,
152+
o_len: *mut u32,
153+
) -> u32 {
154+
let input_i8: &[i8] = unsafe { std::slice::from_raw_parts(i, i_len as usize) };
155+
let input: &[u8] = unsafe { std::mem::transmute(input_i8) };
156+
157+
let raw_out_i8: &mut [i8] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) };
158+
let mut raw_out: &mut [u8] = unsafe { std::mem::transmute(raw_out_i8) };
159+
160+
return match altbn128_pairing_precompiled_impl(input) {
161+
Ok(result) => {
162+
let written = raw_out.write(result.as_ref());
163+
if let Ok(bytes_written) = written {
164+
unsafe { *o_len = bytes_written as u32 };
165+
0u32
166+
} else {
167+
1u32
168+
}
169+
}
170+
Err(_error) => {
171+
1u32
172+
}
173+
}
174+
}
175+
176+
fn altbn128_pairing_precompiled_impl(data: &[u8]) -> Result<Rc<Vec<u8>>, RuntimeError> {
177+
use bn::{pairing, AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2};
178+
179+
fn read_one(s: &[u8]) -> Result<(G1, G2), RuntimeError> {
180+
let ax =
181+
Fq::from_slice(&s[0..32]).map_err(|_| RuntimeError::BadFormat)?;
182+
let ay = Fq::from_slice(&s[32..64])
183+
.map_err(|_| RuntimeError::BadFormat)?;
184+
let bay = Fq::from_slice(&s[64..96])
185+
.map_err(|_| RuntimeError::BadFormat)?;
186+
let bax = Fq::from_slice(&s[96..128])
187+
.map_err(|_| RuntimeError::BadFormat)?;
188+
let bby = Fq::from_slice(&s[128..160])
189+
.map_err(|_| RuntimeError::BadFormat)?;
190+
let bbx = Fq::from_slice(&s[160..192])
191+
.map_err(|_| RuntimeError::BadFormat)?;
192+
193+
let ba = Fq2::new(bax, bay);
194+
let bb = Fq2::new(bbx, bby);
195+
196+
let b = if ba.is_zero() && bb.is_zero() {
197+
G2::zero()
198+
} else {
199+
AffineG2::new(ba, bb)
200+
.map_err(|_| RuntimeError::BadFormat)?
201+
.into()
202+
};
203+
let a = if ax.is_zero() && ay.is_zero() {
204+
G1::zero()
205+
} else {
206+
AffineG1::new(ax, ay)
207+
.map_err(|_| RuntimeError::BadFormat)?
208+
.into()
209+
};
210+
211+
Ok((a, b))
212+
}
213+
214+
if data.len() % 192 != 0 {
215+
return Err(RuntimeError::BadFormat);
216+
}
217+
218+
let ele_len = data.len() / 192;
219+
220+
let mut acc = Gt::one();
221+
for i in 0..ele_len {
222+
let (a, b) = read_one(&data[i * 192..i * 192 + 192])?;
223+
acc = acc * pairing(a, b);
224+
}
225+
226+
let mut output = vec![0u8; 32];
227+
if acc == Gt::one() {
228+
output[31] = 1u8;
229+
}
230+
231+
Ok(Rc::new(output))
232+
}

build.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,13 @@ EOF
220220
}
221221

222222
build_secp256k1
223+
build_altbn128
224+
build_ipa_multipoint
225+
build_secp256r1
226+
223227
if [[ "$ARCH" != "aarch64" ]]; then
224-
build_altbn128
225228
build_bls12_381
226-
build_ipa_multipoint
227229
fi
228-
build_secp256r1
230+
229231
build_jars
230232
exit

0 commit comments

Comments
 (0)